package com.ygqh.baby.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.constant.RedisConstant;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.handler.SettlementHandler;
import com.ygqh.baby.handler.ShoppingCarHandler;
import com.ygqh.baby.handler.SplitSendDetailHandler;
import com.ygqh.baby.mapper.YgOrderDetailMapper;
import com.ygqh.baby.mapper.YgOrderMapper;
import com.ygqh.baby.model.*;
import com.ygqh.baby.model.wdt.qyb.PushOrderToWdtResult;
import com.ygqh.baby.observer.Observable.OrderPaySuccessObservable;
import com.ygqh.baby.observer.OrderPayModel;
import com.ygqh.baby.po.*;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.task.YgAsynClient;
import com.ygqh.baby.template.AbstractSplitListTemplate;
import com.ygqh.baby.utils.CarComparator;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.KdNiaoUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
public class YgOrderServiceImpl extends AbstractService implements YgOrderService {
    protected final Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private YgOrderMapper ygOrderMapper;
    @Autowired
    private YgOrderDetailMapper orderDetailMapper;
    @Autowired
    private YgPromotionService promotionService;
    @Autowired
    private YgSkuService skuService;
    @Autowired
    private YgShoppingCarService shoppingCarService;
    @Autowired
    private YgCouponDetailService couponDetailService;
    @Autowired
    private YgProductService productService;
    @Autowired
    private YgUserAddressService userAddressService;
    @Autowired
    private YgUserService userService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    @Autowired
    private YgStockService stockService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private WxMpMessageService wxMpMessageService;
    @Autowired
    private YgOrderLogService ygOrderLogService;
    @Autowired
    private YgOrderPaymentService ygOrderPaymentService;
    @Autowired
    private YgAsynClient wdtSyncOrderClient;
    @Autowired
    private YgLogisticsService ygLogisticsService;
    @Autowired
    private YgProductImagesService ygProductImagesService;
    @Autowired
    private DocumentConstant documentConstant;
    @Autowired
    private YgSalesPromotionService ygSalesPromotionService;
    @Autowired
    private YgGroupBuyingService ygGroupBuyingService;

    @Autowired
    private YgBmdismService ygBmdismService;
    @Autowired
    private ScheduleJobService scheduleJobService;
    @Autowired
    private RedisDao redisDao;
    @Value("${express.price}")
    private BigDecimal expressPrice;
    @Value("${express.limitPrice}")
    private BigDecimal expressLimitPrice;
    @Value("${kdniao.EBusinessID}")
    private String EBusinessID;
    @Value("${kdniao.AppKey}")
    private String AppKey;
    @Value("${kdniao.ReqURL}")
    private String ReqURL;
    @Value("${promotion.link}")
    protected String promotionLink;
    @Value("${manjian.ladder}")
    protected Boolean ladderMJ;
    @Value("${manjian.smal_new.filterId}")
    private Long filterManjianId;
    @Autowired
    private YgPromotionService ygPromotionService;
    @Autowired
    private YgProductActionGiftService ygProductActionGiftService;
    @Autowired
    private YgCardCouponDetailService ygCardCouponDetailService;
    @Autowired
    private YgPlatformService ygPlatformService;
    @Autowired
    private OrderPaySuccessObservable orderPaySuccessObservable;
    @Autowired
    private YgCouponService ygCouponService;
    private final static ExecutorService executorService = Executors.newFixedThreadPool(3);
    @Autowired
    private YgPrepayBookRecordService ygPrepayBookRecordService;
    @Autowired
    private KidsOrderLogisticsService kidsOrderLogisticsService;
    @Autowired
    private TrustoneService trustoneService;
    @Autowired
    private ShoppingCarHandler shoppingCarHandler;
    @Autowired
    private SettlementHandler settlementHandler;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private SplitSendDetailHandler splitSendDetailHandler;

    @Override
    public List<YgOrder> find() {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name()).andOrderStatusEqualTo(OrderStatus.WaitingPay.name());
        return ygOrderMapper.selectByExample(example);
    }

    @Override
    public int findCount() {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygOrderMapper.countByExample(example);
    }

    @Override
    public YgOrder findById(Long id) {
        return ygOrderMapper.selectByPrimaryKey(id);
    }

    @Override
    public YgOrder findByOrderId(Long orderId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name()).andOrderIdEqualTo(orderId);
        List<YgOrder> list = ygOrderMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public int save(YgOrder ygOrder) {
        return ygOrderMapper.insertSelective(ygOrder);
    }

    @Override
    public int update(YgOrder ygOrder) {
        return ygOrderMapper.updateByPrimaryKeySelective(ygOrder);
    }

    @Override
    public int updateByOrderId(YgOrder ygOrder) {
        return this.updateByOrderId(ygOrder, DataStatus.Valid);
    }

    @Override
    public int updateByOrderId(YgOrder ygOrder, DataStatus status) {
        Assert.notNull(ygOrder.getOrderId());
        Assert.notNull(status);
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdEqualTo(ygOrder.getOrderId()).andStatusEqualTo(status.name());
        return ygOrderMapper.updateByExampleSelective(ygOrder, example);
    }

    @Override
    public ResultSet<YgOrder> search(QueryInfo queryInfo, Long supplierId, Long orderId, PayType payType, OrderStatus orderStatus, Date startDate, Date endDate,
                                     String q, String userName, String telPhone, String validOrder, String appType, String sourceCode, OrderType orderType, String productName) {
        List<YgOrder> list = ygOrderMapper.selectSuper(queryInfo, supplierId, orderId, payType, orderStatus, startDate, endDate, q, userName, telPhone,
                validOrder, appType, sourceCode, orderType, productName);

        int count = ygOrderMapper.countSuper(supplierId, orderId, payType, orderStatus, startDate, endDate, q, userName, telPhone, validOrder, appType,
                sourceCode, orderType, productName);
        ResultSet<YgOrder> resultSet = new ResultSet<YgOrder>(count, list);
        return resultSet;
    }

    @Override
    public int deleteSoft(Long[] orderIds, Long userId) {
        Assert.notEmpty(orderIds);
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdIn(Arrays.asList(orderIds)).andStatusEqualTo(DataStatus.Valid.name());
        YgOrder record = new YgOrder();
        record.setStatus(DataStatus.Delete);
        return ygOrderMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteSoft(Long orderId, Long userId) {
        return this.deleteSoft(new Long[]{orderId}, userId);
    }

    @Override
    public int saveOrUpdate(YgOrder ygOrder) {
        int r = 0;
        if (ygOrder.getId() != null) {
            r = this.update(ygOrder);
        } else {
            r = this.save(ygOrder);
        }
        return r;
    }

    @Override
    public Message toSettlementPage(Long[] skuIds, Long userId) {
        return this.toSettlementPage(skuIds, userId, false);
    }


    @Override
    public Message toSettlementPage(Long[] skuIds, Long userId, Boolean distribution) {
        return settlementHandler.toSettlementPage(skuIds, userId, distribution);
    }


    /**
     * 校验优惠卷
     *
     * @param couponDetail
     * @param productPrice 商品总额 含加价购金额
     * @param onlySpecial
     * @return
     */
    @Override
    public Message validateCoupon(YgCouponDetail couponDetail, BigDecimal productPrice, Boolean onlySpecial, List<YgShoppingCarModel> carList,
                                  SalesPlatform salesPlatform) {
        if (couponDetail != null) {
            if (onlySpecial) {
                return Message.error("特例品不能单独使用优惠券", couponDetail.getId());
            }
            long currentDate = DateConvertUtils.getDateStart(new Date()).getTime();
            long startDate = couponDetail.getStartDate().getTime();
            long endDate = couponDetail.getEndDate().getTime();
            // 尚未开始或已过期
            if (startDate - currentDate > 0 || endDate - currentDate < 0) {
                return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
            }
            // 该优惠卷已使用过，请选择其它优惠卷。
            if (couponDetail.getUseStatus().equals(CouponStatus.Used)) {
                return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
            }
            if (salesPlatform != null && !couponDetail.getCoupon().getSalesPlatform().equals(salesPlatform)) { // 该优惠券销售平台不对应
                return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
            }
            if (couponDetail.getCoupon().getSceneType().equals(SceneType.ALL)) { // 全场券
                if (productPrice.compareTo(couponDetail.getCoupon().getLimitPrice()) < 0) { // 商品总金额不满足该优惠卷使用条件
                    return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
                }
                return Message.success(couponDetail.getFaceValue());
            }
            return validateCouponWithBrandAndProduct(couponDetail, productPrice, carList);
        }
        return Message.success(new BigDecimal(0));

    }

    /**
     * 对品牌券和商品券的特殊处理
     *
     * @param couponDetail
     * @param productPrice
     * @param carList
     * @return
     */
    private Message validateCouponWithBrandAndProduct(YgCouponDetail couponDetail, BigDecimal productPrice,
                                                      List<YgShoppingCarModel> carList) {
        YgCoupon model = couponDetail.getCoupon();
        List<Long> relateIdList = model.getRelateIdList();
        BigDecimal price = BigDecimal.ZERO;
        for (YgShoppingCarModel carModel : carList) {
            if (carModel.getIsSpecial()) {
                // 特例品不参与优惠券
                continue;
            }
            // 符合券的规则
            if ((SceneType.Brand.equals(model.getSceneType()) && relateIdList.contains(carModel.getBrandId()))
                    || (SceneType.Product.equals(model.getSceneType()) && relateIdList.contains(carModel.getProductId()))) {
                price = price.add(carModel.getRealSalesPrice().multiply(BigDecimal.valueOf(carModel.getAmount())));
            }
        }
        if (price.compareTo(BigDecimal.ZERO) == 0) {
            return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
        }
        if (model.getLimitPrice() != null && price.compareTo(model.getLimitPrice()) < 0) {
            return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
        }
        /*StringBuffer sb = new StringBuffer();
        for (YgShoppingCarModel carModel : carList) {
            if (carModel.getIsSpecial() || carModel.getSalesType().equals(PromotionType.ManZeng)) {
                continue;
            }
            if (carModel.getSalesType().equals(PromotionType.JiaJiaGou)) { // 加价购商品不记品牌券和商品券
                productPrice = productPrice.subtract(carModel.getPromotionPrice());
                continue;
            }
            sb.append(",").append(carModel.getProductId());
        }
        if (productPrice.compareTo(couponDetail.getCoupon().getLimitPrice()) < 0) { // 商品总金额不满足该优惠卷使用条件
            return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
        }
        if (sb.length() > 0) {
            boolean validateUsable = ygCouponService.validateUsable(couponDetail.getCoupon().getSceneType(), couponDetail.getCoupon().getProductIds(),
                    sb.substring(1)); // 校验优惠券的可用性
            if (!validateUsable) {
                return Message.error(documentConstant.getCOUPON_UNUSEABLE(), couponDetail);
            }
        }*/
        return Message.success(couponDetail.getFaceValue());
    }

    private Message validateStockNum(List<YgStock> stockList, List<YgShoppingCarModel> carList) {

        for (YgShoppingCarModel car : carList) {
            for (YgStock stock : stockList) {
                if (car.getSkuCode().equals(stock.getSkuCode())) {
                    if (car.getAmount().compareTo(stock.getAmount()) > 0) {
                        return Message.error("【" + car.getProductName() + "】" + documentConstant.getSTOCK_LESS(), car.getProductName());
                    }
                }
            }
        }
        return Message.success("");
    }

    @Override
    public Map<String, BigDecimal> getProductPrice(List<YgShoppingCarModel> cars) {

        final BigDecimal zero = new BigDecimal("0.00");
        Map<String, BigDecimal> map = new HashMap<String, BigDecimal>();
        BigDecimal productPrice = zero;
        BigDecimal specialPrice = zero;
        BigDecimal newCustomPrice = zero;
        BigDecimal vipPrice = zero;
        if (CollectionUtils.isEmpty(cars)) {
            map.put("productPrice", productPrice);
            map.put("specialPrice", specialPrice);
            map.put("vipDisPrice", vipPrice);
            return map;
        }
        Boolean isNewCustom = userService.isNewCustom(cars.get(0).getUserId());
        for (YgShoppingCarModel car : cars) {
            if (car.getSalesType().equals(PromotionType.Ordinary)) {
                BigDecimal salesPrice = car.getRealSalesPrice();
                BigDecimal vPrice = car.getVipPrice();
                if (vPrice == null || vPrice.compareTo(new BigDecimal("0.00")) == 0) {
                    vPrice = car.getRealSalesPrice();
                }
                productPrice = productPrice.add(salesPrice.multiply(new BigDecimal(car.getQuantity())));
                vipPrice = vipPrice.add(vPrice.multiply(new BigDecimal(car.getQuantity())));
                if (car.getIsSpecial()) {
                    if (isNewCustom && car.getNewCustomPrice().compareTo(zero) > 0 && newCustomPrice.compareTo(zero) == 0) {
                        newCustomPrice = car.getNewCustomPrice();

                        specialPrice = specialPrice.add(salesPrice.multiply(new BigDecimal(car.getQuantity() - 1)));
                        specialPrice = specialPrice.add(newCustomPrice);
                    } else {
                        specialPrice = specialPrice.add(salesPrice.multiply(new BigDecimal(car.getQuantity())));

                    }

                }
            }
            if (car.getSalesType().equals(PromotionType.JiaJiaGou)) {
                productPrice = productPrice.add(car.getPromotionPrice());
                vipPrice = vipPrice.add(car.getPromotionPrice());
            }
        }
        map.put("productPrice", productPrice);
        map.put("specialPrice", specialPrice);
        map.put("vipDisPrice", productPrice.subtract(vipPrice));
        return map;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Message commitOrder(Long userId, String userName, Long userAddressId, Long couponDetailId, BigDecimal totalPrice, AppType appType, PayType payType,
                               String sourceCode, BigDecimal accountPrice, String formId, String userRemark, Long expressCardId, OrderType orderType,
                               List<YgShoppingCarModel> carList, String platformNo, String identityNo, SalesPlatform salesPlatform) {

        if (carList == null || carList.size() <= 0) {
            return Message.error(documentConstant.getCAR_IS_EMPTY(), null);
        }

        // 校验收货地址
        Message addressMsg = userAddressService.validateUserAddress(userId, userAddressId, identityNo, carList, orderType);
        if (!Message.isSuccess(addressMsg)) {
            return addressMsg;
        }
        Map<String, Object> addressExtra = (Map<String, Object>) addressMsg.getExtra();
        YgUserAddress address = (YgUserAddress) addressExtra.get("address");
        // 是否为保税仓订单
        Boolean trustoneOrderFlag = (Boolean) addressExtra.get("trustoneOrderFlag");

        ygBmdismService.getBestBmdism(carList);
        shoppingCarService.doNewCusBussness(carList);
        // 校验自选包

        CarPackPriceResult packPriceResult = shoppingCarHandler.getPackAndNewCustomDisAndSpecialPrice(carList);
        ygOrderLogService.addOrderLog(1l, OrderStatus.WaitingPay, userName, "验证自选包结果：" + JSON.toJSONString(packPriceResult));

        BigDecimal packDisPrice = packPriceResult.getPackDisPrice();
        BigDecimal specialPrice = packPriceResult.getSpecialPrice();
        BigDecimal newCustomDisPrice = packPriceResult.getNewCustomDisPrice();
        List<YgShoppingCarModel> packs = packPriceResult.getCarList();

        Set<String> skuCodes = new HashSet<>();
        YgShoppingCar jiajiagouCar = null;
        YgShoppingCar manzengCar = null;
        String jiajiagouSkuCode = null;
        String manzengSkuCode = null;
        // 商品总额（不含加价购价格）
        BigDecimal ordinaryPrice = new BigDecimal(0);
        // 商品总额（含加价购金额）
        BigDecimal productPrice = new BigDecimal(0);

        // 多买多折优惠
        BigDecimal bmdisPrice = new BigDecimal(0);

        List<Long> productIds = new ArrayList<>();

        int i = 0;
        int j = 0;
        for (YgShoppingCarModel car : carList) {
            BigDecimal realSalesPrice = car.getRealSalesPrice();
            // 验证商品上下架
            if (car.getSaleStatus().equals(ProductStatus.InStock)) {
                return Message.error("【" + car.getProductName() + "】已下架", car.getSkuId());
            }
            if (car.getSalesType().equals(PromotionType.Ordinary) || car.getSalesType().equals(PromotionType.Bmdism)) {
                productIds.add(car.getProductId());
                skuCodes.add(car.getSkuCode());
                ordinaryPrice = ordinaryPrice.add(realSalesPrice.multiply(new BigDecimal(car.getQuantity())));
                productPrice = productPrice.add(realSalesPrice.multiply(new BigDecimal(car.getQuantity())));
            }
            if (car.getSalesType().equals(PromotionType.JiaJiaGou)) {
                jiajiagouCar = new YgShoppingCar();
                jiajiagouCar.setSkuId(car.getSkuId());
                jiajiagouCar.setSalesType(car.getSalesType());
                jiajiagouCar.setPromotionPrice(car.getPromotionPrice());

                jiajiagouSkuCode = car.getSkuCode();
                skuCodes.add(car.getSkuCode());

                productPrice = productPrice.add(car.getPromotionPrice());
                i++;
            }
            if (car.getSalesType().equals(PromotionType.ManZeng)) {
                manzengCar = new YgShoppingCar();
                manzengCar.setSkuId(car.getSkuId());
                manzengCar.setSalesType(car.getSalesType());

                manzengSkuCode = car.getSkuCode();
                skuCodes.add(car.getSkuCode());
                j++;
            }
            if (car.getSalesType().equals(PromotionType.Bmdism)) {
                BigDecimal dis = (realSalesPrice.subtract(car.getPromotionPrice())).multiply(new BigDecimal(car.getQuantity().toString()));
                bmdisPrice = bmdisPrice.add(dis);
            }

        }
        if (i > 1) {
            return Message.error(documentConstant.getJIAJIAGOU_AMOUNT_MORE(), null);
        }
        if (j > 1) {
            return Message.error(documentConstant.getMANZENG_AMOUNT_MORE(), null);
        }
        List<YgStock> stockList = stockService.findBySkuCodes(skuCodes.toArray(new String[skuCodes.size()]));
        // 存在某一商品既在普通商品中又在赠品中，校验库存是 在普通商品的数量上+1
        for (YgShoppingCarModel model : carList) {
            // amount 为校验库存冗余字段
            model.setAmount(model.getQuantity());
            if (manzengCar != null) {
                if (model.getSalesType().equals(PromotionType.Ordinary) && model.getSkuCode().equals(manzengSkuCode)) {
                    Long amount = model.getQuantity() + YgShoppingCar.ONE;
                    model.setAmount(amount);
                }
            }
            if (jiajiagouCar != null) {
                if (model.getSalesType().equals(PromotionType.Ordinary) && model.getSkuCode().equals(jiajiagouSkuCode)) {
                    Long amount = model.getQuantity() + YgShoppingCar.ONE;
                    model.setAmount(amount);
                }
            }
        }
        // 校验库存
        Message stockNumMsg = this.validateStockNum(stockList, carList);
        ygOrderLogService.addOrderLog(1l, OrderStatus.WaitingPay, userName, "验证库存结果：msgType:" + stockNumMsg.getType() + ";msg:" + stockNumMsg.getContent());
        if (!stockNumMsg.getType().equals(Message.Type.success)) {
            return stockNumMsg;
        }

        // 校验促销是否满足条件
        // 验证加价购
        Message jiaJiaGouMsg = shoppingCarHandler.validateJiaJiaGou(ordinaryPrice, jiajiagouCar, salesPlatform);
        ygOrderLogService.addOrderLog(1l, OrderStatus.WaitingPay, userName, "验证加价购结果：msgType:" + jiaJiaGouMsg.getType() + ";msg:" + jiaJiaGouMsg.getContent());
        if (!jiaJiaGouMsg.getType().equals(Message.Type.success)) {
            return jiaJiaGouMsg;
        }

        /**
         * 1、 优惠优先级按 满减、特例品，优惠券、运费顺序来。
         * 如：现有活动为满100-5，满199包邮，且用户有满200-50的优惠券，这时如果用户的初始订单金额为250，
         * 最后用户需要支付的金额计算过程为： 250-5=245>200(满足优惠券使用条件)
         * 245-50=195<199（不满足包邮条件，需加收运费） 195+10=205（用户最后需要支付的金额）
         */
        // 新客及自选包优惠后的金额
        BigDecimal price = productPrice.subtract(newCustomDisPrice).subtract(packDisPrice).subtract(bmdisPrice);

        // 校验优惠卷
        YgCouponDetail couponDetail = couponDetailService.findById(couponDetailId, userId);
        // 优惠卷金额
        BigDecimal couponPrice;
        // 自选包设置为特例品导致特例品金额多减 ,在给加回来。
        BigDecimal validPrice = price.subtract(specialPrice);
        if (validPrice.compareTo(ZERO) > 0) {
            Message couponMsg = this.validateCoupon(couponDetail, validPrice, false, carList, salesPlatform);
            if (!couponMsg.getType().equals(Message.Type.success)) {
                return couponMsg;
            }
            couponPrice = (BigDecimal) couponMsg.getExtra();
        } else {
            couponPrice = ZERO;
        }
        price = price.subtract(couponPrice);
        // 满减
        Map<String, Object> manJian = this.getManJianPrice(price, formId, userId);// 满减金额
        Boolean useCoupon = (Boolean) manJian.get("useCoupon");
        BigDecimal manJianPrice = (BigDecimal) manJian.get("manjianPrice");
        if (!useCoupon) {
            manJianPrice = new BigDecimal(0);
        }

        // 当商品金额-新客及自选包优惠金额 - 满减金额 -优惠券金额 < 0
        BigDecimal price4exp = price.subtract(manJianPrice);
        if (price4exp.compareTo(new BigDecimal("0")) < 0) {
            price4exp = new BigDecimal("0");
            ygOrderLogService.addOrderLog(userId, OrderStatus.WaitingPay, userName, "结算校验：因使用优惠券金额大于满减后的商品金额,couponDetailId=" + couponDetailId);
        }

        BigDecimal expPrice = this.getExpressPrice(price4exp, userId);// 运费
        YgCardCouponDetail expressCard = null;
        // 验证包邮卡券
        if (expPrice.compareTo(ZERO) > 0 && expressCardId != null) {
            expressCard = ygCardCouponDetailService.findById(expressCardId);
            if (expressCard == null || expressCard.getUseStatus().equals(UseStatus.Used)) {
                return Message.error("包邮卡券异常，请重试", null);
            }
            if (expressCard.getEndDate().before(DateConvertUtils.getDateStart(new Date()))) {
                return Message.error("包邮卡券过期，请重试", null);
            }
            expPrice = ZERO;
        }
        // 订单总金额 （最终支付金额） = 商品总额(含加价购金额) -优惠卷金额 - 满减金额+ 运费
        BigDecimal realTotalPrice = price4exp.add(expPrice);
        if (realTotalPrice.compareTo(totalPrice) != 0) {
            return Message.error(documentConstant.getORDER_PRICE_YOUWU(),
                    carList.toString() + "订单金额明细：userName =" + userName + " ;productPrice=" + productPrice + ";newCustomDisPrice=" + newCustomDisPrice
                            + ";packDisPrice=" + packDisPrice + ";manJianPrice" + manJianPrice + ";couponPrice=" + couponPrice + ";expPrice=" + expPrice
                            + ";realTotalPrice=" + realTotalPrice + ";totalPrice=" + totalPrice);
        }

        // 验证满赠
        Message manZengMsg = shoppingCarHandler.validateManZeng(realTotalPrice, manzengCar, productIds, salesPlatform);
        ygOrderLogService.addOrderLog(userId, OrderStatus.WaitingPay, userName, "验证满赠结果：msgType:" + manZengMsg.getType() + ";msg:" + manZengMsg.getContent());
        if (!manZengMsg.getType().equals(Message.Type.success)) {
            return manZengMsg;
        }

        if (accountPrice.compareTo(new BigDecimal(0)) > 0) {

            YgUserBalance balance = ygUserBalanceService.findByUserId(userId);
            // 账户余额小于当前是使用金额
            if (balance.getBalancePrice().compareTo(accountPrice) < 0) {
                return Message.error("账户余额有误，请重试。", null);
            }
            // 使用的虚拟金额大于订单的实际金额
            if (accountPrice.compareTo(realTotalPrice) > 0) {
                return Message.error("账户余额有误，请重试。", null);
            }
        }
        realTotalPrice = realTotalPrice.subtract(accountPrice);
        // 保存主单
        Message message = this.saveMainOrder(address, couponDetail, couponPrice, userId, userName, realTotalPrice, accountPrice, productPrice, manJianPrice,
                expPrice, newCustomDisPrice, packDisPrice, new BigDecimal("0.00"), bmdisPrice, appType, payType, sourceCode, carList, packs, formId, null,
                orderType == null ? OrderType.Ordinary : orderType, userRemark, expressCard, platformNo, trustoneOrderFlag, Boolean.TRUE, salesPlatform);

        return message;
    }

    /**
     * 保存主单
     *
     * @param userAddressId
     * @param couponDetail
     * @param couponPrice
     * @param userId
     * @param userName
     * @param totalPrice
     * @param productPrice
     * @param manJianPrice
     * @param expPrice
     * @param newCustomDisPrice
     * @param packDisPrice
     * @param groupDisPrice
     * @param payType
     * @param sourceCode
     * @param carList
     * @param groupBuyId
     * @param orderType
     * @param userRemark
     * @param expressCard
     * @param platformNo
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    @Override
    public Message saveMainOrder(YgUserAddress address, YgCouponDetail couponDetail, BigDecimal couponPrice, Long userId, String userName,
                                 BigDecimal totalPrice, BigDecimal accountPrice, BigDecimal productPrice, BigDecimal manJianPrice, BigDecimal expPrice, BigDecimal newCustomDisPrice,
                                 BigDecimal packDisPrice, BigDecimal groupDisPrice, BigDecimal bmdisPrice, AppType appType, PayType payType, String sourceCode,
                                 List<YgShoppingCarModel> carList, List<YgShoppingCarModel> packs, String formId, Long groupBuyId, OrderType orderType, String userRemark,
                                 YgCardCouponDetail expressCard, String platformNo, Boolean trustonerOrderFlag, Boolean reduceStockFlag, SalesPlatform salesPlatform) {

        BigDecimal specialPrice = BigDecimal.ZERO;
        if (StringUtil.isNotBlank(userName) && userName.contains("specialPrice")) {
            String[] split = userName.split(",");
            userName = split[0];
            specialPrice = new BigDecimal(split[1].substring(13));
        }

        // 保存订单
        YgOrder order = new YgOrder();
        // 设置收货信息
        order.setReceiver(address.getReceiver());
        order.setProvinceName(address.getProvinceName());
        order.setCityName(address.getCityName());
        order.setAreaName(address.getAreaName());
        order.setAddress(address.getAddress());
        order.setTelPhone(address.getTelPhone());
//		order.setPostCode(address.getPostCode());
        order.setUserRemark(userRemark);
        if (trustonerOrderFlag) {
            order.setPostCode(address.getIdentityNo());
        }
        // 保存主单

        if (couponDetail != null) {
            couponPrice = couponDetail.getFaceValue();
            order.setCouponDetailId(couponDetail.getId());
        }
        Long orderId = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());

        order.setOrderId(orderId);
        order.setParentId(orderId);
        order.setUserId(userId);
        order.setTotalPrice(totalPrice);
        order.setProductPrice(productPrice);
        order.setExpressPrice(expPrice);
        order.setManjianPrice(manJianPrice);
        order.setYouhuijuanPrice(couponPrice);
        order.setGroupDisPrice(groupDisPrice);
        order.setNewCustomDisPrice(newCustomDisPrice);
        order.setPackDisPrice(packDisPrice);
        order.setBmdisPrice(bmdisPrice);
        order.setPayType(payType);
        order.setSupplierId(null);
        order.setOrderStatus(OrderStatus.WaitingPay);
        order.setCreateTime(new Date());
        order.setSourceCode(sourceCode);
        order.setAccountPrice(accountPrice);
        order.setFormId(formId);
        order.setOrderType(orderType);
        order.setReleationId(groupBuyId);
        order.setExpressCompany(specialPrice.toString());
        YgPlatform platform = ygPlatformService.findByPlatformNo(platformNo);
        if (platform != null) {
            order.setPlatformNo(platformNo);
            order.setPlatformName(platform.getName());
        }

        if (StringUtils.isNotBlank(formId)) {
            appType = AppType.Small;
        }
        order.setAppType(appType);
        List<YgStock> stocks = new ArrayList<YgStock>();

        List<YgOrderDetail> detailList = new ArrayList<YgOrderDetail>();
        for (YgShoppingCarModel carModel : carList) {
            YgOrderDetail detail = new YgOrderDetail();
            detail.setOrderId(orderId);
            detail.setProductName(carModel.getProductName());
            if (carModel.getIsSpecial()) {
                detail.setPromotionType(PromotionType.IsSpecial);
            } else {
                detail.setPromotionType(carModel.getSalesType());
            }
            detail.setQuantity(carModel.getQuantity());
            detail.setSize(carModel.getSizeName());
            detail.setSupplierId(carModel.getSupplierId());
            detail.setSkuCode(carModel.getSkuCode());
            detail.setSkuId(carModel.getSkuId());
            detail.setUnitName(carModel.getUnitName());
            detail.setImageUrl(carModel.getImagePath());
            detail.setShortName(carModel.getShortName());

            detail.setShareRate(carModel.getShareRate());
            detail.setForeverRate(carModel.getForeverRate());


            detail.setSalePrice(carModel.getRealSalesPrice());

            if (carModel.getSalesType().equals(PromotionType.ManZeng) || carModel.getSalesType().equals(PromotionType.JiaJiaGou)) {
                detail.setSalePrice(carModel.getPromotionPrice());
            }


            setRemark(order, detail, carModel, packs);
            detailList.add(detail);

            YgStock stock = new YgStock();
            stock.setSkuCode(carModel.getSkuCode());
            stock.setAmount(carModel.getQuantity());
            stocks.add(stock);
        }
        // ygSalesPromotionService.activityForManZeng(detailList, stocks,
        // sourceCode, totalPrice, userName, orderType);
        ygSalesPromotionService.activityForSingleGift(detailList, stocks, sourceCode, totalPrice, userName, orderType);

        int row = 0;
        try {
            row = this.save(order);
            ygOrderLogService.addOrderLog(order.getOrderId(), order.getOrderStatus(), userName, "主订单保存成功 ;order=" + order.toString());
            logger.info("主单保存成功。orderId =" + orderId);
        } catch (Exception e) {
            ygOrderLogService.addOrderLog(order.getOrderId(), order.getOrderStatus(), userName, "主订单保存失败;order=" + order.toString());
            logger.error("主单保存失败。orderInfo:" + order.toString());
            e.printStackTrace();
            return Message.error("提交订单失败！", orderId);
        }

        if (row > 0) {

            orderDetailMapper.insertBatch(detailList);
            if (reduceStockFlag) {
                // 扣减库存
                stockService.reduceStock(stocks, "saveMainOrder");
            }
            // 扣减虚拟账户金额
            if (accountPrice.compareTo(new BigDecimal(0)) > 0) {
                int i = ygUserBalanceService.reduceAcountPrice(userId, accountPrice);
                if (i > 0 && accountPrice.compareTo(new BigDecimal("0.00")) > 0) {
                    // 扣减成功在，生成一条流水
                    ygUserBalanceService.addBalanceDetail(userId, orderId.toString(), accountPrice.multiply(new BigDecimal(-1)),
                            BalanceType.Balance, OperationType.PayOrder, "支付订单", platformNo);
                    // ygAccountDetailService.add(orderId, userId,
                    // PriceType.PayOrder, accountPrice.multiply(new
                    // BigDecimal(-1)), "支付订单");
                }
            }
            // 删除购物车
            shoppingCarService.deleteCarByCheck(userId, salesPlatform);
            // 把当前使用的优惠券消费掉
            if (couponDetail != null) {
                couponDetail.setUseStatus(CouponStatus.Used);
                couponDetail.setUseTime(new Date());
                couponDetailService.update(couponDetail);
            }
            // 更新包邮卡使用状态
            if (expressCard != null) {
                YgCardCouponDetail updateRecord = new YgCardCouponDetail();
                updateRecord.setId(expressCard.getId());
                updateRecord.setUseStatus(UseStatus.Used);
                updateRecord.setUseTime(new Date());
                updateRecord.setRelationId(orderId);
                ygCardCouponDetailService.update(updateRecord);
            }
        }

        Map<String, Long> map = new HashMap<String, Long>();
        map.put("orderId", order.getOrderId());
        map.put("groupBuyId", groupBuyId);
        return Message.success(map);
    }

    private void setRemark(YgOrder order, YgOrderDetail detail, YgShoppingCarModel carModel, List<YgShoppingCarModel> packs) {
        if (carModel.getSalesType().equals(PromotionType.ManZeng)) {
            detail.setSalePrice(new BigDecimal(0));
            BigDecimal limitPrice;
            List<YgPromotion> manzeng = ygPromotionService.findPromotionBySkuId(detail.getSkuId(), PromotionType.ManZeng, order.getTotalPrice());
            if (CollectionUtils.isEmpty(manzeng)) {

                limitPrice = ygProductActionGiftService.getSalePriceOfActionProduct(carModel.getProductId());
            } else {
                limitPrice = manzeng.get(0).getLimitPrice();
            }
            detail.setRemark(PromotionType.ManZeng + "," + limitPrice.toString());
        }
        if (carModel.getNewCustomPrice() != null && carModel.getNewCustomPrice().compareTo(new BigDecimal(0)) > 0) {
            detail.setRemark(PromotionType.NewCustom + "," + carModel.getNewCustomPrice().toString());
        }
        if (carModel.getSalesType().equals(PromotionType.Bmdism)) {
            detail.setRemark(PromotionType.Bmdism + "," + carModel.getPackId() + "," + carModel.getRealSalesPrice());

        }
        if (packs != null) {
            for (YgShoppingCarModel pack : packs) {
                if (pack.getSkuId().equals(carModel.getSkuId())) {
                    StringBuilder remark = new StringBuilder();
                    remark.append(PromotionType.Pack).append(",").append(pack.getPackPrice()).append(",").append(pack.getProductAmount())
                            .append(",").append(pack.getPackId()).append(",").append(pack.getQuantity()).append(",").append(pack.getUseCoupon());

                    if (carModel.getNewCustomPrice() != null && carModel.getNewCustomPrice().compareTo(new BigDecimal(0)) > 0
                            && carModel.getQuantity().compareTo(pack.getQuantity()) > 0) {
                        remark.append(",").append(pack.getNewCustomPrice());
                    }
                    detail.setRemark(remark.toString());
                    if (!Constant.YIJIADIAN_PLATFORM_NO.equals(order.getPlatformNo())) {
                        detail.setShareRate(new BigDecimal("0.05"));
                    }
                }
            }

        }
    }

    @Override
    public List<YgOrderModel> findOrderList(QueryInfo queryInfo, Long userId, OrderStatus orderStatus) {
        return findOrderList(queryInfo, userId, orderStatus == null ? null : orderStatus, Constant.YIIGOO_PLATFORM_NO);
    }

    @Override
    public List<YgOrderModel> findOrderList(QueryInfo queryInfo, Long userId, OrderStatus orderStatus, String platformNo) {
        return ygOrderMapper.selectOrderList(queryInfo, userId, orderStatus == null ? null : orderStatus.name(), platformNo);
    }

    @Override
    public YgOrder findOrderDetail(Long orderId) {
        YgOrder order = this.findByOrderId(orderId);
        List<YgLogistics> logistics = ygLogisticsService.findByOrderId(order.getOrderId().toString());
        if (logistics != null && logistics.size() > 0) {
            order.setLogisticsList(logistics);
        }
        YgOrderDetailExample example = new YgOrderDetailExample();
        example.createCriteria().andOrderIdEqualTo(order.getOrderId());
        List<YgOrderDetail> list = orderDetailMapper.selectByExample(example);
        YgOrderPayment payment = ygOrderPaymentService.findByOrderId(order.getOrderId().toString());
        if (payment != null) {
            order.setOrderPayCode(Long.parseLong(payment.getOrderPayCode()));
        }
        if (list != null && list.size() > 0) {
            order.setOrderDetail(list);
        }
        return order;
    }

    @Override
    public YgOrderInfoModel findOrderInfo(Long orderId, Long userId) {
        return ygOrderMapper.selectOrderInfo(orderId, userId);
    }

    @Override
    public BigDecimal getExpressPrice(BigDecimal productPrice, Long userId) {
        return getExpressPrice(productPrice, userId, SalesPlatform.Yiigoo);
    }

    @Override
    public BigDecimal getExpressPrice(BigDecimal productPrice, Long userId, SalesPlatform salesPlatform) {
        if (SalesPlatform.Yijiadian.equals(salesPlatform)) {
            if (userService.isNewCustomByYijiadian(userId)) {
                // 壹家店新客免邮
                return BigDecimal.ZERO;
            }
        } else if (userService.isVip(userId)) {
            // 壹果老会员免邮
            return BigDecimal.ZERO;
        }
        BigDecimal expPrice = expressPrice;
        BigDecimal expLimitPrice = expressLimitPrice;
        String key = String.format(RedisConstant.EXPRESS_KEY, salesPlatform);
        String express = redisDao.get(key);
        if (StringUtil.isNotBlank(express)) {
            try {
                @SuppressWarnings("unchecked")
                Map<String, Integer> map = JSONObject.parseObject(express, Map.class);
                expPrice = new BigDecimal(map.get("price"));
                expLimitPrice = new BigDecimal(map.get("limitPrice"));
            } catch (Exception e) {
                logger.error("从redis中获取运费失败;" + e.getMessage());
                e.printStackTrace();
            }
        }
        if (productPrice.compareTo(expLimitPrice) >= 0) {
            expPrice = BigDecimal.ZERO;
        }
        return expPrice;
    }

    @Override
    public Map<String, Object> getManJianPrice(BigDecimal productPrice, String formId, Long userId) {
        List<YgPromotionModel> manjianList = promotionService.findOwnPromotionList(PromotionType.ManJian);
        BigDecimal manjianPrice = new BigDecimal(0);
        Map<String, Object> map = new HashMap<String, Object>();
        Boolean useCoupon = true;
        if (manjianList != null && manjianList.size() > 0) {
            YgPromotionModel manjian = filterManjia(manjianList, formId, userId);
            if (manjian != null) {
                BigDecimal limitPrice = manjian.getLimitPrice();
                BigDecimal discountPrice = manjian.getDiscountPrice();
                if (ladderMJ) {
                    // BigDecimal d = productPrice.divide(limitPrice,
                    // BigDecimal.ROUND_HALF_UP);
                    // int i = 1;
                    // while (true) {
                    // if (i > d.intValue()) {
                    // break;
                    // }
                    // BigDecimal limit = limitPrice.multiply(new
                    // BigDecimal(i));
                    // BigDecimal price =
                    // productPrice.subtract(discountPrice.multiply(new
                    // BigDecimal(i
                    // - 1)));
                    // if (price.compareTo(limit) >= 0) {
                    // productPrice = price.subtract(discountPrice);
                    // manjianPrice = manjianPrice.add(discountPrice);
                    // } else {
                    // break;
                    // }
                    // i++;
                    // }
                    BigDecimal d = productPrice.divide(limitPrice, 0, RoundingMode.DOWN);
                    manjianPrice = discountPrice.multiply(d);
                } else {
                    if (productPrice.compareTo(limitPrice) >= 0) {
                        manjianPrice = discountPrice;
                    }
                }
                if (manjianPrice.compareTo(BigDecimal.ZERO) > 0) {
                    useCoupon = manjian.getUseCoupon();
                }
            }
        }
        map.put("manjianPrice", manjianPrice);
        map.put("useCoupon", useCoupon);
        return map;
    }

    // 过滤指定满减活动
    private YgPromotionModel filterManjia(List<YgPromotionModel> manjianList, String formId, Long userId) {
        // 小程序--新客 下单
        if (StringUtils.isNotBlank(formId)) {
            Boolean newCustom = userService.isNewCustom(userId);
            if (newCustom) {
                return manjianList.get(0);
            }
        }
        // 其他条件，过滤指定满减活动
        List<YgPromotionModel> list = manjianList.stream().filter(o -> o.getId().compareTo(filterManjianId) != 0).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public int splitOrder(Long orderId, BigDecimal totalPrice, PayType payType) {

        Long detailAmount = 0L;
        // 获取主单信息
        YgOrder mainOrder = this.findOrderDetailByOrderId(orderId);
        if (!mainOrder.getOrderStatus().equals(OrderStatus.WaitingPay)) {
            return 2;
        }
        if (totalPrice.compareTo(mainOrder.getTotalPrice()) != 0) {
            ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "微信支付回调", "该订单支付金额与实际金额不符;");
            logger.warn("该订单支付金额与实际金额不符;orderId=" + orderId);
        }

        List<YgOrderDetail> orderDetails = mainOrder.getOrderDetail();
        BigDecimal totalProductPrice = mainOrder.getProductPrice();//
        BigDecimal totalCouponPrice = mainOrder.getYouhuijuanPrice();// 优惠卷金额费
        BigDecimal totalExpressPrice = mainOrder.getExpressPrice();// 运费
        BigDecimal totalManjianPrice = mainOrder.getManjianPrice();// 满减金额

        BigDecimal lastExpressPrice = mainOrder.getExpressPrice();// 剩余运费
        BigDecimal lastManjianPrice = mainOrder.getManjianPrice();// 剩余满减金额
        BigDecimal lastCouponPrice = mainOrder.getYouhuijuanPrice();// 剩余优惠卷金额
        // 根据不同商家进行拆单
        Map<Long, List<YgOrderDetail>> subDetailMap = new LinkedHashMap<Long, List<YgOrderDetail>>();
        List<Long> supplierIds = new ArrayList<Long>();

        for (YgOrderDetail detail : orderDetails) {
            detailAmount += detail.getQuantity();
            List<YgOrderDetail> subDetails = subDetailMap.get(detail.getSupplierId());
            if (subDetails == null) {
                subDetails = new ArrayList<YgOrderDetail>();
                subDetailMap.put(detail.getSupplierId(), subDetails);
                supplierIds.add(detail.getSupplierId());
            }
            subDetails.add(detail);
        }

        // 存在多个商家
        List<Long> orderIds = new ArrayList<Long>();
        orderIds.add(mainOrder.getOrderId());
        BigDecimal zero = new BigDecimal("0.00");
        if (supplierIds.size() > 1) {
            for (int i = 0; i < supplierIds.size(); i++) {

                BigDecimal productPrice = zero;// 商品总额

                BigDecimal couponPrice = zero;// 优惠卷金额费
                BigDecimal expressPrice = zero;// 运费
                BigDecimal manjianPrice = zero;// 满减金额

                BigDecimal groupDisPrice = zero;// 拼团
                BigDecimal newCustomDisPrice = zero;// 满减金额
                BigDecimal packDisPrice = zero;// 满减金额
                BigDecimal bmdisPrice = zero;// 满减金额

                Long orderCode = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());
                orderIds.add(orderCode);

                List<YgOrderDetail> List = subDetailMap.get(supplierIds.get(i));
                for (YgOrderDetail detail : List) {
                    productPrice = productPrice.add(detail.getSalePrice().multiply(new BigDecimal(detail.getQuantity())));
                    if (i != 0) {
                        detail.setOrderId(orderCode);
                    }
                }
                // 按商品金额比例分摊 满减，运费，优惠卷金额
                expressPrice = productPrice.divide(totalProductPrice, 2, BigDecimal.ROUND_HALF_UP).multiply(totalExpressPrice);
                manjianPrice = productPrice.divide(totalProductPrice, 2, BigDecimal.ROUND_HALF_UP).multiply(totalManjianPrice);
                couponPrice = productPrice.divide(totalProductPrice, 2, BigDecimal.ROUND_HALF_UP).multiply(totalCouponPrice);
                if (i != supplierIds.size() - 1) {
                    lastExpressPrice = lastExpressPrice.subtract(expressPrice);
                    lastManjianPrice = lastManjianPrice.subtract(manjianPrice);
                    lastCouponPrice = lastCouponPrice.subtract(couponPrice);
                }

                if (i == 0) {
                    mainOrder.setExpressPrice(expressPrice);
                    mainOrder.setManjianPrice(manjianPrice);
                    mainOrder.setYouhuijuanPrice(couponPrice);
                    mainOrder.setSupplierId(supplierIds.get(0));
                    mainOrder.setProductPrice(productPrice);
                    mainOrder.setTotalPrice(productPrice.add(expressPrice).subtract(manjianPrice).subtract(couponPrice));
                    mainOrder.setOrderStatus(OrderStatus.WaitingSend);
                    mainOrder.setPaidPrice(mainOrder.getTotalPrice());
                    mainOrder.setPaidTime(new Date());
                    mainOrder.setPayType(payType);
                    this.update(mainOrder);
                    continue;
                } else {

                    YgOrder order = new YgOrder();
                    order.setOrderId(orderCode);
                    order.setParentId(orderId);
                    order.setUserId(mainOrder.getUserId());
                    order.setProductPrice(productPrice);

                    order.setPayType(mainOrder.getPayType());
                    order.setSupplierId(supplierIds.get(i));
                    order.setOrderStatus(OrderStatus.WaitingSend);
                    order.setCreateTime(new Date());
                    order.setSourceCode(mainOrder.getSourceCode());
                    order.setReceiver(mainOrder.getReceiver());
                    order.setProvinceName(mainOrder.getProvinceName());
                    order.setCityName(mainOrder.getCityName());
                    order.setAreaName(mainOrder.getAreaName());
                    order.setAddress(mainOrder.getAddress());
                    order.setTelPhone(mainOrder.getTelPhone());
                    order.setPostCode(mainOrder.getPostCode());
                    order.setCouponDetailId(mainOrder.getCouponDetailId());

                    if (i != supplierIds.size() - 1) {
                        order.setExpressPrice(expressPrice);
                        order.setManjianPrice(manjianPrice);
                        order.setYouhuijuanPrice(couponPrice);
                        order.setTotalPrice(productPrice.add(expressPrice).subtract(manjianPrice).subtract(couponPrice));
                        order.setPaidPrice(order.getTotalPrice());

                    } else {
                        order.setExpressPrice(lastExpressPrice);
                        order.setManjianPrice(lastManjianPrice);
                        order.setYouhuijuanPrice(lastCouponPrice);
                        order.setTotalPrice(productPrice.add(lastExpressPrice).subtract(lastManjianPrice).subtract(lastCouponPrice));
                        order.setPaidPrice(order.getTotalPrice());
                    }
                    order.setPaidTime(new Date());

                    this.save(order);
                    orderDetailMapper.updateBatch(List);
                }

            }
        } else {
            mainOrder.setSupplierId(supplierIds.get(0));
            mainOrder.setOrderStatus(OrderStatus.WaitingSend);
            mainOrder.setPaidPrice(mainOrder.getTotalPrice());
            mainOrder.setPaidTime(new Date());
            mainOrder.setPayType(payType);

            this.update(mainOrder);
        }

        // 记录订单日志
        ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "系统拆单", "订单支付成功");
        // 支付消息
        wxMpMessageService.sendOrderPaySuccessMsg(mainOrder.getUserId(), orderId, mainOrder.getTotalPrice(), mainOrder.getOrderDetail().get(0).getProductName(),
                mainOrder.getOrderDetail().size());
        Boolean isSync = this.isSyncOrder(mainOrder, detailAmount);
        // 同步订单到旺店通
        if (isSync) {
            wdtSyncOrderClient.syncQybOrder(orderIds);
            // wdtSyncOrderClient.syncOrder(orderIds);
        }
        return 1;
    }

    @Override
    public int splitOrderV2(Long orderId, BigDecimal totalPrice, PayType payType) {
        return this.splitOrderV3(orderId, totalPrice, payType, new Date());
    }

    @Override
    public int splitOrderV3(Long orderId, BigDecimal totalPrice, PayType payType, Date paidTime) {

        // 获取主单信息
        YgOrder mainOrder = this.findOrderDetailByOrderId(orderId);
        if (mainOrder == null) {
            return 1;
        }
        if (!mainOrder.getOrderStatus().equals(OrderStatus.WaitingPay)) {
            return 2;
        }
        Map<String, Object> data = getOrderStatusAndIsSync(mainOrder);
        OrderStatus orderStatus = (OrderStatus) data.get("orderStatus");
        if (totalPrice.compareTo(mainOrder.getTotalPrice()) != 0) {
            ygOrderLogService.addOrderLog(orderId, orderStatus, "支付回调", "该订单支付金额与实际金额不符;payType=" + payType);
            logger.warn("该订单支付金额与实际金额不符;orderId=" + orderId);
        }
        Long supplierId = mainOrder.getOrderDetail().get(0).getSupplierId();
        mainOrder.setSupplierId(supplierId);
        mainOrder.setOrderStatus(orderStatus);
        mainOrder.setPaidPrice(totalPrice);
        mainOrder.setPaidTime(paidTime);
        mainOrder.setPayType(payType);

        this.update(mainOrder);

        // 支付消息
        wxMpMessageService.sendOrderPaySuccessMsg(mainOrder.getUserId(), orderId, mainOrder.getTotalPrice(), mainOrder.getOrderDetail().get(0).getProductName(),
                mainOrder.getOrderDetail().size());

        // 记录订单日志
        ygOrderLogService.addOrderLog(orderId, orderStatus, "系统拆单", "订单支付成功;payType=" + payType);
        Boolean isSync = (Boolean) data.get("isSync");
        List<Long> orderIds = new ArrayList<Long>();
        orderIds.add(orderId);
        // 同步订单到旺店通
        if (isSync) {
            wdtSyncOrderClient.syncQybOrder(orderIds);
            trustoneService.pushTrustonerOrderAndDeclareCustoms(orderId);
            splitSendDetailHandler.splitSendDetails(orderId);
        }
        return 1;
    }

    private Map<String, Object> getOrderStatusAndIsSync(YgOrder mainOrder) {
        Long detailAmount = mainOrder.getOrderDetail().stream().map(d -> d.getQuantity()).reduce(0L, (a, b) -> a + b);
        Boolean isSync = true;
        OrderStatus orderStatus = OrderStatus.WaitingSend;
        if (mainOrder.getOrderType().equals(OrderType.GroupBuying) || mainOrder.getOrderType().equals(OrderType.HeXiao)) {
            YgGroupBuying groupBuying = ygGroupBuyingService.findById(mainOrder.getReleationId());
            // 是否重置完成时间
            boolean resetCompleteTime = false;
            if (groupBuying.getCompleteStatus().equals(CompleteStatus.UnComplete)) {
                isSync = false;
                orderStatus = OrderStatus.WaitingCheck;
                if (groupBuying.getCompleteTime() == null || groupBuying.getCompleteTime().before(new Date())) {
                    // 拼团完成时间小于当前时间，延期拼团完成时间
                    resetCompleteTime = true;
                }
            }
            ygGroupBuyingService.updateGroupBuyAmount(groupBuying.getId(), detailAmount, resetCompleteTime);
        } else if (mainOrder.getOrderType().equals(OrderType.CardCoupon)) { // 卡券订单不推送
            isSync = false;
        }
        Map<String, Object> data = new HashMap<>();
        data.put("isSync", isSync);
        data.put("orderStatus", orderStatus);
        return data;
    }

    @Deprecated
    private Boolean isSyncOrder(YgOrder mainOrder, Long detailAmount) {
        Boolean isSync = true;
        if (mainOrder.getOrderType().equals(OrderType.GroupBuying) || mainOrder.getOrderType().equals(OrderType.HeXiao)) {
            YgGroupBuying groupBuying = ygGroupBuyingService.findById(mainOrder.getReleationId());
            if (groupBuying.getCompleteStatus().equals(CompleteStatus.UnComplete)) {
                isSync = false;
            }
            ygGroupBuyingService.updateGroupBuyAmount(groupBuying.getId(), detailAmount, Boolean.FALSE);
        } else if (mainOrder.getOrderType().equals(OrderType.CardCoupon)) { // 卡券订单不推送
            isSync = false;
        }
        return isSync;
    }

    @Override
    public YgOrder findOrderDetailByOrderId(Long orderId) {

        return this.findOrderDetailByOrderId(orderId, DataStatus.Valid);
    }

    @Override
    public YgOrder findOrderDetailByOrderId(Long orderId, DataStatus status) {
        YgOrder order = ygOrderMapper.selectOrderDetailByOrderId(orderId, status);
        return order;
    }

    @Override
    public List<YgOrder4CommentModel> findWaitingComment(Long orderId, Long userId) {
        return orderDetailMapper.selectWaitingComment(orderId, userId);
    }

    @Override
    public int cancelOrder(Long orderId, Long userId, String userName, String cancelReason) {
        Assert.notNull(orderId);
        int row = 0;
        YgOrder ygOrder = this.findOrderDetailByOrderId(orderId);
        if (ygOrder != null && ygOrder.getUserId().equals(userId) && ygOrder.getOrderStatus().equals(OrderStatus.WaitingPay)) {
            ygOrder.setOrderStatus(OrderStatus.TradeClosed);
            ygOrder.setCancelTime(new Date());
            ygOrder.setCancelReason(cancelReason);
            row = this.update(ygOrder);
            // 记录订单日志
            ygOrderLogService.addOrderLog(orderId, OrderStatus.TradeClosed, userName, "用户取消订单");

            // 还库存
            if (ygOrder.getOrderDetail() != null) {
                List<YgStock> stockList = new ArrayList<YgStock>();
                for (YgOrderDetail detail : ygOrder.getOrderDetail()) {
                    YgStock stock = new YgStock();
                    stock.setSkuCode(detail.getSkuCode());
                    stock.setAmount(detail.getQuantity());
                    stockList.add(stock);
                }
                stockService.backStock(stockList, "用户取消订单");
            }
            // 还优惠卷
            if (ygOrder.getCouponDetailId() != null) {

                YgCouponDetail ygCouponDetail = new YgCouponDetail();
                ygCouponDetail.setId(ygOrder.getCouponDetailId());
                ygCouponDetail.setUseStatus(CouponStatus.Received);
                couponDetailService.update(ygCouponDetail);
            }
            // 还虚拟账户金额
            if (ygOrder.getAccountPrice().compareTo(new BigDecimal(0)) > 0) {
                ygUserBalanceService.backAcountPrice(userId, ygOrder.getAccountPrice());
                ygUserBalanceService.addBalanceDetail(userId, orderId.toString(), ygOrder.getAccountPrice(),
                        BalanceType.Balance, OperationType.CancelOrder,
                        "用户主动取消订单", ygOrder.getPlatformNo());
                // ygAccountDetailService.add(orderId,
                // userId,PriceType.CancelOrder, ygOrder.getAccountPrice(),
                // "取消订单");
            }
            // 还包邮卡
            ygCardCouponDetailService.returnExpressCard(ygOrder.getUserId(), ygOrder.getOrderId());
            // 异步处理绑定订单的活动记录
            ygPrepayBookRecordService.asyncUpdateRecordByCancelOrder(ygOrder.getOrderId());
            return row;
        }

        return row;
    }

    @Override
    public List<Map<String, Object>> findCountByOrderStatus(Long userId) {
        return findCountByOrderStatus(userId, Constant.YIIGOO_PLATFORM_NO);
    }

    @Override
    public List<Map<String, Object>> findCountByOrderStatus(Long userId, String platformNo) {
        return ygOrderMapper.selectCountByOrderStatus(userId, platformNo);
    }

    @Override
    public YgCommissionOrderModel findOrderForBalance(String sourceCode) {
        return ygOrderMapper.selectOrderForBalance(sourceCode);
    }

    @Override
    public int cancelOrderByTask(List<Long> orderIds, String cancelReason) {
        return ygOrderMapper.cancelOrderByTask(orderIds, cancelReason);
    }

    @Override
    public List<YgOrder> findOrderForSendPayInvitation(Integer limitTime) {
        return ygOrderMapper.selectOrderForSendPayInvitation(limitTime);
    }

    @Override
    public List<YgOrder> findOrderForBalaceTask(Integer limitTime) {
        return ygOrderMapper.selectOrderForBalaceTask(limitTime);
    }

    @Override
    public List<YgOrder> findOrderIdForCancelTask(Date currentDate) {
        return ygOrderMapper.selectOrderIdForCancelTask(currentDate);
    }

    @Override
    public List<YgOrder> findOrder4SuccessTask(Date date) {
        return ygOrderMapper.selectOrder4SuccessTask(date);
    }

    @Override
    public int orderStatusForSuccessTask(List<Long> orderIds) {
        return ygOrderMapper.orderStatusForSuccessTask(orderIds);
    }

    @Override
    public Message getLogisticsInfo(String expCode, String expNo) {
        try {

            String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

            Map<String, String> params = new HashMap<String, String>();
            params.put("RequestData", KdNiaoUtil.urlEncoder(requestData, "UTF-8"));
            params.put("EBusinessID", EBusinessID);
            params.put("RequestType", "1002");
            String dataSign = KdNiaoUtil.encrypt(requestData, AppKey, "UTF-8");
            params.put("DataSign", KdNiaoUtil.urlEncoder(dataSign, "UTF-8"));
            params.put("DataType", "2");

            String result = KdNiaoUtil.sendPost(ReqURL, params);
            ObjectMapper mapper = new ObjectMapper();
            Map map = mapper.readValue(result, Map.class);

            Boolean boo = (Boolean) map.get("Success");
            Object Traces = map.get("Traces");

            if (boo) {
                return Message.success(Traces);
            }

        } catch (Exception e) {
            logger.error("获取物流信息失败;expCode=" + expCode + ";" + e.getMessage(), e);
            e.printStackTrace();
        }
        return Message.error(null);
    }

    @Override
    public Boolean isPaid(Long orderId) {
        YgOrder order = this.findByOrderId(orderId);
        if (order != null) {
            if (!order.getOrderStatus().equals(OrderStatus.TradeClosed) && !order.getOrderStatus().equals(OrderStatus.WaitingPay)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public List<Map<String, Object>> getOrderReport(Date startDate, Date endDate, String userName, String sourceCode, String q, String orderStatus,
                                                    String telPhone, Boolean validOrder, String productName) {
        return ygOrderMapper.selectOrderExportReport(startDate, endDate, userName, sourceCode, q, orderStatus, telPhone, validOrder, productName);
    }

    @Override
    public List<Comment4TaskModel> findProductComment4Task(Date limitDate) {
        return orderDetailMapper.selectProductComment4Task(limitDate);
    }

    @Override
    public int updateStatus4SendByTask(List<YgOrder> orderList, List<YgOrderDetail> sendDetailList) {
        if (!CollectionUtils.isEmpty(sendDetailList) && !CollectionUtils.isEmpty(orderList)) {
            ygOrderMapper.updateStatus4SendByTask(orderList);
            orderDetailMapper.updateDetailSendBatch(sendDetailList);
        }
        return 1;
    }

    @Override
    public void doBussness4PaySuccess(String paymentCode, String transactionId, BigDecimal totalPrice, AppType appType, PayType payType) {
        ygOrderLogService.addOrderLog(Long.parseLong(paymentCode), OrderStatus.WaitingSend, "doBussness4PaySuccess", "执行doBussness4PaySuccess");
        // 支付成功进行拆单
        YgOrderPayment payment = null;
        try {
            payment = ygOrderPaymentService.findByPayCode(paymentCode);
            Long orderId = Long.parseLong(payment.getOrderId());
            int i = this.splitOrderV2(orderId, totalPrice, payType);
            ygOrderLogService.addOrderLog(Long.parseLong(paymentCode), OrderStatus.WaitingSend, "doBussness4PaySuccess", "拆单结束，返回结果 result=" + i);
            // 1:正常 0:金额不匹配，2：订单已经拆单
            if (i != 2) {
                // 记录支付流水
                payment.setPaidPrice(totalPrice);
                payment.setPaySuccessTime(new Date());
                payment.setPayType(payType);
                payment.setAppType(appType);
                payment.setTransactionId(transactionId);
                ygOrderPaymentService.writeBackPayment(payment);
                ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "系统", "订单支付成功后，处理业务逻辑成功");
            } else {
                // 该订单重复支付
                ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "微信支付回调", "该订单存在重复支付;支付流水号：" + paymentCode);

            }
            orderPaySuccessObservable.paySuccess(new OrderPayModel(orderId, totalPrice, payType, paymentCode));
        } catch (Exception e) {
            logger.error("订单支付成功，处理业务逻辑失败。===paymentCode :" + paymentCode + ";" + ExceptionUtil.getExceptionMsg(e));
            ygOrderLogService.addOrderLog(Long.parseLong(paymentCode), OrderStatus.WaitingSend, "系统",
                    "订单支付成功后，处理业务逻辑失败;支付流水号：" + paymentCode + ";" + e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public Map<String, Long> orderIsComment(Long orderId) {
        return ygOrderMapper.orderIsComment(orderId);
    }

    @Override
    public List<YgOrder> findOrderFor30Day(Date startDate, Date endDate) {
        startDate = DateConvertUtils.getDateStart(startDate);
        endDate = DateConvertUtils.getDateStart(endDate);
        return ygOrderMapper.findOrderFor30Day(startDate, endDate);
    }

    @Override
    public Message getNewCusAndPackPrice(List<YgShoppingCarModel> cars, Long userId, Boolean isValid) {
        Boolean isNewCustom = userService.isNewCustom(userId);
        Map<Long, BigDecimal> newCusMap = new HashMap<Long, BigDecimal>();

        BigDecimal zero = new BigDecimal("0.00");
        BigDecimal packDisPrice = zero;
        BigDecimal newCustomDisPrice = zero;
        Map<Long, List<YgShoppingCarModel>> subDetailMap = new LinkedHashMap<Long, List<YgShoppingCarModel>>();
        List<Long> keys = new ArrayList<Long>();
        // 按照销售价排序
        CarComparator carComparator = new CarComparator();
        Collections.sort(cars, carComparator);
        for (YgShoppingCarModel car : cars) {
            BigDecimal realSalesPrice = car.getRealSalesPrice();
            if (car.getSalesType().equals(PromotionType.Ordinary)) {
                if (isNewCustom && car.getNewCustomPrice().compareTo(zero) > 0) {
                    BigDecimal newCusPrice = newCusMap.get(car.getSkuId());
                    if (newCusPrice == null) {
                        newCusMap.put(car.getSkuId(), car.getNewCustomPrice());
                        newCustomDisPrice = newCustomDisPrice.add(realSalesPrice.subtract(car.getNewCustomPrice()));
                    }
                } else {
                    car.setNewCustomPrice(zero);
                }
                if (car.getPackId() != null && car.getPackId() > 0) {
                    List<YgShoppingCarModel> subDetails = subDetailMap.get(car.getPackId());
                    if (subDetails == null) {
                        subDetails = new ArrayList<YgShoppingCarModel>();
                        subDetailMap.put(car.getPackId(), subDetails);
                        keys.add(car.getPackId());
                    }
                    subDetails.add(car);
                }
            }
        }
        Message msg = this.getProductPackDisPrice(subDetailMap, keys);
        Map<String, Object> result = (Map<String, Object>) msg.getExtra();
        packDisPrice = (BigDecimal) result.get("packDisPrice");
        // 既是特例品又是自选包的自选包优惠
        BigDecimal packDisPriceWithSpecial = (BigDecimal) result.get("packDisPriceWithSpecial");
        // 自选包优惠为负
        if (packDisPrice.compareTo(ZERO) < 0) {
            packDisPrice = ZERO;
        }
        result.put("packDisPrice", packDisPrice);
        result.put("newCustomDisPrice", newCustomDisPrice);
        result.put("packDisPriceWithSpecial", packDisPriceWithSpecial);
        return Message.success(result);
    }

    public Message getProductPackDisPrice(Map<Long, List<YgShoppingCarModel>> subDetailMap, List<Long> keys) {
        Map<String, Object> map = new HashMap<String, Object>();
        BigDecimal zero = new BigDecimal(0);
        BigDecimal salesPrice = zero;
        BigDecimal packPrice = zero;
        BigDecimal packDisPrice = zero;

        // 既是自选包又是特例品的优惠价
        BigDecimal packDisPriceWithSpecial = zero;

        // 记录满足自选包条件的数据，用于在保存订单时标记自选包
        List<YgShoppingCarModel> packs = new ArrayList<YgShoppingCarModel>();
        for (Long key : keys) {
            List<YgShoppingCarModel> packList = new ArrayList<YgShoppingCarModel>();
            List<YgShoppingCarModel> carList = subDetailMap.get(key);
            int amount = 0;
            int packProductNum = 0;// 自选包数量
            BigDecimal price = zero;
            BigDecimal currSalesPrice = zero;
            int selectNum = 0;
            int i = 0;
            for (YgShoppingCarModel model : carList) {

                i++;
                amount = model.getQuantity().intValue();
                price = model.getRealSalesPrice();
                packProductNum = model.getProductAmount().intValue();
                if (amount + selectNum > packProductNum) {
                    amount = packProductNum - selectNum;
                    selectNum = packProductNum;

                } else {
                    selectNum = selectNum + amount;
                }
                currSalesPrice = currSalesPrice.add(price.multiply(new BigDecimal(amount)));
                if (i == carList.size() && selectNum < packProductNum)
                    currSalesPrice = zero;
                if (selectNum >= packProductNum) {
                    salesPrice = salesPrice.add(currSalesPrice);
                    packList.add(model);
                    if (currSalesPrice.compareTo(model.getPackPrice()) < 0) {
                        final BigDecimal packPriceNew = currSalesPrice;
                        packList.stream().forEach(p -> {
                            p.setPackPrice(packPriceNew);
                        });
                    }
                    packPrice = packPrice.add(model.getPackPrice());

                    if (model.getIsSpecial()) {
                        // 如果是特例品
                        packDisPriceWithSpecial = packDisPriceWithSpecial.add(currSalesPrice.subtract(model.getPackPrice()));
                    }

                    packs.addAll(packList);
                    break;
                }
                packList.add(model);
                if (i == carList.size() && selectNum < packProductNum) {
                    packList.clear();
                }
                /*
                 * if (amount < model.getProductAmount().intValue()) {
                 * salesPrice =
                 * salesPrice.add(model.getSalesPrice().multiply(new
                 * BigDecimal(model.getQuantity()))); packs.add(model); } else
                 * if (amount == model.getProductAmount().intValue()) {
                 * salesPrice =
                 * salesPrice.add(model.getSalesPrice().multiply(new
                 * BigDecimal(model.getQuantity()))); packPrice
                 * =packPrice.add(model.getPackPrice()); packs.add(model);
                 * break; } else { int i = model.getProductAmount().intValue() -
                 * (amount - model.getQuantity().intValue()); salesPrice =
                 * salesPrice.add(model.getSalesPrice().multiply(new
                 * BigDecimal(i))); packPrice =
                 * packPrice.add(model.getPackPrice()); packs.add(model); break;
                 * }
                 */
            }
        }
        if (packPrice.compareTo(ZERO) > 0) {
            packDisPrice = salesPrice.subtract(packPrice);
        }

        map.put("packDisPrice", packDisPrice);
        map.put("packDisPriceWithSpecial", packDisPriceWithSpecial);
        map.put("packs", packs);
        return Message.success("", map);
    }

    @Override
    public Boolean hasPayOrder(Long userId) {
        YgOrderExample example = new YgOrderExample();
        List<String> orderStatus = new ArrayList<String>();
        orderStatus.add(OrderStatus.TradeClosed.name());
        orderStatus.add(OrderStatus.WaitingPay.name());
        example.createCriteria().andUserIdEqualTo(userId).andOrderStatusNotIn(orderStatus).andStatusEqualTo(DataStatus.Valid.name());
        List<YgOrder> list = ygOrderMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public List<YgOrder> findCancelOrderForBalaceTask(Integer day) {
        return ygOrderMapper.findCancelOrderForBalaceTask(day);
    }

    @Override
    public List<YgOrder> selectIntervalOrder(Date date) {
        return ygOrderMapper.selectIntervalOrder(date);
    }

    @Override
    public Message confirmReceipt(Long orderId, Long userId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdEqualTo(orderId).andUserIdEqualTo(userId).andOrderStatusEqualTo(OrderStatus.WaitingSign.name());
        YgOrder record = new YgOrder();
        record.setOrderId(orderId);
        record.setOrderStatus(OrderStatus.TradeSuccess);
        record.setConfirmReceiveTime(new Date());
        int row = ygOrderMapper.updateByExampleSelective(record, example);
        ygOrderLogService.addOrderLog(orderId, OrderStatus.TradeSuccess, userId + "", "用户主动确认完成");
        if (row > 0) {
            return Message.success(row);
        } else {
            return Message.error(row);
        }
    }

    @Override
    public int countUnCommentComplete(Long userId) {
        return countUnCommentComplete(userId, Constant.YIIGOO_PLATFORM_NO);
    }

    @Override
    public int countUnCommentComplete(Long userId, String platformNo) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andUserIdEqualTo(userId)
                .andOrderStatusEqualTo(OrderStatus.TradeSuccess.name())
                .andStatusEqualTo(DataStatus.Valid.name())
                .andPlatformNoEqualTo(platformNo)
                .andCommentStatusEqualTo(CommentStatus.UnComplete.name());

        return ygOrderMapper.countByExample(example);
    }

    @Override
    public Message saveImportOrder(List<YgOrder4ImportModel> agentOrderList, Long userId) {
        if (agentOrderList != null && agentOrderList.size() > 0) {
            List<YgStock> stocks = new ArrayList<YgStock>();
            Map<String, List<YgOrder4ImportModel>> subDetailMap = new LinkedHashMap<String, List<YgOrder4ImportModel>>();
            List<String> keys = new ArrayList<String>();

            Map<String, Long> skuCountMap = new HashMap<String, Long>();
            List<String> skuCodes = new ArrayList<String>();
            for (YgOrder4ImportModel model : agentOrderList) {
                Long count = skuCountMap.get(model.getSkuCode());
                if (count == null) {
                    count = model.getQuantity();
                    skuCountMap.put(model.getSkuCode(), count);
                    skuCodes.add(model.getSkuCode());
                } else {
                    count = count + model.getQuantity();
                    skuCountMap.put(model.getSkuCode(), count);
                }

                List<YgOrder4ImportModel> subDetails = subDetailMap.get(model.getTelPhone());
                if (subDetails == null) {
                    subDetails = new ArrayList<YgOrder4ImportModel>();
                    subDetailMap.put(model.getTelPhone(), subDetails);
                    keys.add(model.getTelPhone());
                }
                subDetails.add(model);
            }
            // 校验库存
            Message msg = checkImportOrderStock(skuCodes, skuCountMap);
            if (msg.getType().equals(Message.Type.error)) {
                return msg;
            }
            List<YgOrder> orderList = new ArrayList<YgOrder>();
            if (keys.size() > 0) {
                for (String key : keys) {
                    List<YgOrder4ImportModel> list = subDetailMap.get(key);
                    YgOrder order = new YgOrder();
                    Long orderCode = list.get(0).getOrderId();
                    if (orderCode == 0)
                        orderCode = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());
                    order.setOrderId(orderCode);
                    order.setParentId(orderCode);
                    order.setUserId(userId);
                    order.setReceiver(list.get(0).getReceiver());
                    order.setProvinceName(list.get(0).getProvinceName());
                    order.setCityName(list.get(0).getCityName());
                    order.setAreaName(list.get(0).getAreaName());
                    order.setAddress(list.get(0).getAddress());
                    order.setTelPhone(key);
                    order.setSourceCode(list.get(0).getSourceCode());

                    BigDecimal productPrice = new BigDecimal(0);

                    List<YgOrderDetail> detailList = new ArrayList<YgOrderDetail>();
                    for (YgOrder4ImportModel model : list) {
                        YgOrderDetail detail = new YgOrderDetail();
                        YgSku sku = skuService.findBySkuCode(model.getSkuCode(), PromotionType.Ordinary);
                        YgProduct product = productService.findById(sku.getProductId());
                        YgProductImages image = ygProductImagesService.findMainImgByProductId(sku.getProductId());

                        detail.setOrderId(orderCode);
                        detail.setSkuId(sku.getId());
                        detail.setSkuCode(sku.getSkuCode());
                        detail.setSupplierId(product.getSupplierId());
                        detail.setProductName(product.getProductName());
                        detail.setShortName(product.getShortName());
                        detail.setSize(sku.getSizeName());
                        detail.setImageUrl(image.getImagePath());
                        detail.setQuantity(model.getQuantity());
                        detail.setUnitName(product.getUnitName());
                        detail.setPromotionType(PromotionType.Ordinary);

                        if (sku.getWholesalePrice().compareTo(new BigDecimal(0)) == 0) {
                            detail.setSalePrice(sku.getSalesPrice());
                        } else {
                            detail.setSalePrice(sku.getWholesalePrice());
                        }

                        productPrice = productPrice.add(detail.getSalePrice().multiply(new BigDecimal(detail.getQuantity())));
                        detailList.add(detail);

                        YgStock stock = new YgStock();
                        stock.setSkuCode(detail.getSkuCode());
                        stock.setAmount(detail.getQuantity());

                        stocks.add(stock);
                    }

                    // TODO 运费逻辑待定
                    if (expressLimitPrice.compareTo(productPrice) > 0) {
                        order.setExpressPrice(expressPrice);
                    } else {
                        order.setExpressPrice(new BigDecimal(0));
                    }
                    order.setProductPrice(productPrice);
                    order.setTotalPrice(productPrice.add(order.getExpressPrice()));
                    order.setManjianPrice(new BigDecimal(0));
                    order.setYouhuijuanPrice(new BigDecimal(0));
                    order.setOrderStatus(OrderStatus.WaitingPay);

                    order.setPaidPrice(new BigDecimal(0));
                    order.setPayType(PayType.WeChat);
                    order.setNewCustomDisPrice(new BigDecimal(0));
                    order.setPackDisPrice(new BigDecimal(0));
                    order.setSupplierId(null);
                    order.setCreateTime(new Date());
                    order.setStatus(DataStatus.Valid);
                    order.setCommentStatus(CommentStatus.UnComplete);
                    order.setOrderDetail(detailList);
                    orderList.add(order);
                }
            }
            this.saveOrderBatch(orderList);
            stockService.reduceStock(stocks, "saveImportOrder");
        }
        return Message.success("没有订单数据");
    }

    private Message checkImportOrderStock(List<String> skuCodes, Map<String, Long> skuCountMap) {
        List<YgStock> stockList = stockService.findBySkuCodes(skuCodes.toArray(new String[skuCodes.size()]));

        for (YgStock stock : stockList) {
            for (String skuCode : skuCodes) {
                if (skuCode.equals(stock.getSkuCode())) {
                    Long quantity = skuCountMap.get(skuCode);
                    if (quantity.compareTo(stock.getAmount()) > 0) {
                        return Message.error("skuCode为" + skuCode + "的商品库存不足。", skuCode);
                    }
                }
            }
        }
        return Message.success("");
    }

    private int saveOrderBatch(List<YgOrder> orderList) {
        if (orderList != null && orderList.size() > 0) {
            ygOrderMapper.insertBatch(orderList);
            List<YgOrderDetail> detailList = new ArrayList<YgOrderDetail>();
            for (YgOrder ygOrder : orderList) {
                detailList.addAll(ygOrder.getOrderDetail());
            }
            return orderDetailMapper.insertBatch(detailList);
        }
        return 0;
    }

    @Override
    public int saveOrderList(List<YgOrder> orderList) {
        int result = 0;
        if (orderList != null && orderList.size() > 0) {
            List<YgOrder> orders = new ArrayList<>();
            Iterator<YgOrder> iterator = orderList.iterator();
            while (iterator.hasNext()) {
                if (orders.size() == 30) {
                    result += saveOrderBatch(orders);
                    orders.clear();
                }
                orders.add(iterator.next());
            }
            result += saveOrderBatch(orders);
        }
        return result;
    }

    @Override
    public List<YgOrder> findByCreateTime(Date startDate, Date endDate, List<String> oStatus) {
        YgOrderExample example = new YgOrderExample();
        YgOrderExample.Criteria criteria = example.createCriteria();
        if (startDate != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(startDate);
        }
        if (endDate != null) {
            criteria.andCreateTimeLessThan(endDate);
        }
        if (oStatus != null) {
            criteria.andOrderStatusIn(oStatus);
        }
        criteria.andStatusEqualTo(DataStatus.Valid.name());
        return ygOrderMapper.selectByExample(example);
    }

    @Override
    public List<YgOrder> findReturnOrderForBalaceTask(Integer day) {
        return ygOrderMapper.findReturnOrderForBalaceTask(day);
    }

    @Override
    public List<YgOrder> repairOrderDetailRemark() {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andPackDisPriceGreaterThan(new BigDecimal(0))
                .andCreateTimeGreaterThanOrEqualTo(DateConvertUtils.parse("2016-12-01", DateConvertUtils.DATE_FORMAT))
                .andOrderStatusNotEqualTo(OrderStatus.TradeClosed.name());
        List<YgOrder> list = ygOrderMapper.selectByExample(example);
        for (YgOrder ygOrder : list) {
            List<YgOrderDetail> detail = this.findDetailByOrderId(ygOrder.getOrderId());
            ygOrder.setOrderDetail(detail);
        }
        return list;
    }

    private List<YgOrderDetail> findDetailByOrderId(Long orderId) {
        YgOrderDetailExample example = new YgOrderDetailExample();
        example.createCriteria().andOrderIdEqualTo(orderId);
        List<YgOrderDetail> list = orderDetailMapper.selectByExample(example);
        return list;

    }

    @Override
    public int updateDetailBatch(List<YgOrderDetail> detailList) {
        return orderDetailMapper.updateDetailBatch(detailList);
    }

    @Override
    public YgOrder findFirstOrder(Long userId, Date limitDate) {
        return ygOrderMapper.findFirstOrder(userId, limitDate);
    }

    @Override
    public List<YgOrder> findFirstOrderList(Date startDate, Date endDate) {
        return ygOrderMapper.findFirstOrderList(startDate, endDate);
    }

    @Override
    public List<YgOrder> findReturnOrderForPreIncomeToBalance(Integer day) {
        return ygOrderMapper.findReturnOrderForPreIncomeToBalance(day);
    }

    @Override
    public Message commitOrderPt(List<YgPtSkuInfo> skuList, Long userId, String userName, Long userAddressId, Long couponDetailId, BigDecimal totalPrice,
                                 AppType appType, PayType payType, String sourceCode, BigDecimal accountPrice, String formId, Long groupId, Long groupBuyId, OrderType orderType,
                                 String userRemark, String platformNo, String identityNo, SalesPlatform salesPlatform) throws YgException {
        Long amount = 0L;
        List<YgShoppingCarModel> carList = shoppingCarService.findItemInfoPt(skuList, userId, false);

        Message addressMsg = userAddressService.validateUserAddress(userId, userAddressId, identityNo, carList, orderType);
        if (!Message.isSuccess(addressMsg)) {
            return addressMsg;
        }
        Map<String, Object> addressExtra = (Map<String, Object>) addressMsg.getExtra();
        YgUserAddress address = (YgUserAddress) addressExtra.get("address");
        Boolean trustoneOrderFlag = (Boolean) addressExtra.get("trustoneOrderFlag"); // 是否为保税仓订单

        Set<String> skuCodes = new HashSet<String>();
        BigDecimal productPrice = new BigDecimal("0.00");
        BigDecimal specialPrice = new BigDecimal("0.00");
        BigDecimal ptPrice = new BigDecimal("0.00");// 拼团价格

        StringBuilder sb = new StringBuilder();
        for (YgShoppingCarModel car : carList) {
            if (car.getSaleStatus().equals(ProductStatus.InStock)) {
                return Message.error("亲，你购买商品已下架。", car.getProductName());
            }
            if (car.getPromotionPrice().compareTo(new BigDecimal("0")) == 0) {
                sb.append(car.getProductName() + ",skuid=" + car.getSkuId() + ";");
            }
            amount = amount + car.getQuantity();
            ptPrice = ptPrice.add(car.getRealSalesPrice().multiply(new BigDecimal(car.getQuantity())));
            productPrice = productPrice.add(car.getSalesPrice().multiply(new BigDecimal(car.getQuantity())));
            if (car.getSalesType().equals(PromotionType.IsSpecial)) {
                specialPrice = specialPrice.add(car.getSalesPrice().multiply(new BigDecimal(car.getQuantity())));
            }
            skuCodes.add(car.getSkuCode());
            car.setAmount(car.getQuantity());
        }
        if (sb.length() > 0) {
            sb.append("上述商品不是拼团商品");
            throw new YgException("-1", sb.toString());

        }
        List<YgStock> stockList = stockService.findBySkuCodes(skuCodes.toArray(new String[skuCodes.size()]));
        // 校验库存
        Message stockNumMsg = this.validateStockNum(stockList, carList);
        ygOrderLogService.addOrderLog(1l, OrderStatus.WaitingPay, userName, "验证库存结果：msgType:" + stockNumMsg.getType() + ";msg:" + stockNumMsg.getContent());
        if (!stockNumMsg.getType().equals(Message.Type.success)) {
            return stockNumMsg;
        }

        // 校验促销是否满足条件

        /**
         * 1、 优惠优先级按 满减、特例品，优惠券、运费顺序来。
         * 如：现有活动为满100-5，满199包邮，且用户有满200-50的优惠券，这时如果用户的初始订单金额为250，
         * 最后用户需要支付的金额计算过程为： 250-5=245>200(满足优惠券使用条件)
         * 245-50=195<199（不满足包邮条件，需加收运费） 195+10=205（用户最后需要支付的金额）
         */
        // 拼团订单总金额金额
        BigDecimal price = ptPrice;
        Map<String, Object> manJian = this.getManJianPrice(price, formId, userId);
        Boolean useCoupon = (Boolean) manJian.get("useCoupon");

        BigDecimal manJianPrice = (BigDecimal) manJian.get("manjianPrice");
        BigDecimal couponPrice = BigDecimal.ZERO;
        YgCouponDetail couponDetail = null;
        if (useCoupon) {
            BigDecimal couponValidPrice = price.subtract(manJianPrice).subtract(specialPrice);
            Boolean onlySpecial = false;
            if (couponValidPrice.compareTo(BigDecimal.ZERO) > 0) {
                onlySpecial = true;
            }

            if (couponDetailId != null) {
                couponDetail = couponDetailService.findById(couponDetailId, userId);

            }
            Message couponMsg = this.validateCoupon(couponDetail, couponValidPrice, onlySpecial, carList, salesPlatform);
            if (!couponMsg.getType().equals(Message.Type.success)) {
                return couponMsg;
            }
            couponPrice = (BigDecimal) couponMsg.getExtra();
        }

        // 当商品金额-新客及自选包优惠金额 - 满减金额 -优惠券金额 < 0
        BigDecimal price4exp = price.subtract(manJianPrice).subtract(couponPrice);
        if (price4exp.compareTo(BigDecimal.ZERO) < 0) {
            price4exp = new BigDecimal("0");
        }

        // BigDecimal expPrice = this.getExpressPrice(price4exp);// 运费
        BigDecimal expPrice = new BigDecimal(0);// 运费 拼团订单包邮
        // 订单总金额 （最终支付金额） = 商品总额(含加价购金额) -优惠卷金额 - 满减金额+ 运费
        BigDecimal realTotalPrice = price4exp.add(expPrice);
        if (realTotalPrice.compareTo(totalPrice) != 0) {
            return Message.error(documentConstant.getORDER_PRICE_YOUWU(),
                    carList.toString() + "订单金额明细：userName =" + userName + " ;productPrice=" + productPrice + ";manJianPrice" + manJianPrice + ";couponPrice="
                            + couponPrice + ";expPrice=" + expPrice + ";realTotalPrice=" + realTotalPrice + ";totalPrice=" + totalPrice);
        }

        YgUserBalance balance = ygUserBalanceService.findByUserId(userId);
        // 账户余额小于当前是使用金额
        if (balance.getBalancePrice().

                compareTo(accountPrice) < 0) {
            return Message.error("账户余额有误，请重试。");
        }
        // 使用的虚拟金额大于订单的实际金额
        if (accountPrice.compareTo(realTotalPrice) > 0) {
            return Message.error("账户余额有误，请重试。");
        }

        realTotalPrice = realTotalPrice.subtract(accountPrice);
        BigDecimal newCustomDisPrice = new BigDecimal(0);
        BigDecimal packDisPrice = new BigDecimal(0);
        BigDecimal groupDisPrice = productPrice.subtract(ptPrice);

        // 开团
        if ((groupBuyId == null || groupBuyId.intValue() == 0) && orderType.equals(OrderType.GroupBuying)) {
            // 完成数量统一在支付回调中处理
            YgGroupBuying groupBuying = ygGroupBuyingService.addGroupBuyIng(groupId, userId, 0L);
            groupBuyId = groupBuying.getId();
        }

        // 保存主单
        Message message = this.saveMainOrder(address, couponDetail, couponPrice, userId, userName, realTotalPrice, accountPrice, productPrice, manJianPrice,
                expPrice, newCustomDisPrice, packDisPrice, groupDisPrice, new BigDecimal("0"), appType, payType, sourceCode, carList, null, formId, groupBuyId,
                orderType, userRemark, null, platformNo, trustoneOrderFlag, Boolean.TRUE, salesPlatform);

        return message;
    }

    @Override
    public List<Map<String, Object>> getOrderLogisticsReport(Date startDate, Date endDate, String userName, String sourceCode, String q, String orderStatus,
                                                             String telPhone, Boolean validOrder) {
        return ygOrderMapper.selectOrderLogistics(startDate, endDate, userName, sourceCode, q, orderStatus, telPhone, validOrder);
    }

    @Override
    public List<YgOrderDetail> findDetails(Long orderId) {
        return orderDetailMapper.selectByOrderId(orderId);
    }

    @Override
    public List<OrderNotPushModel> findOrderNotPush(Date limitDate) {

        return ygOrderMapper.selectOrderNotPush(limitDate);
    }

    @Override
    public List<YgOrderModel> findOrderListByHeXiao(QueryInfo queryInfo, OrderStatus orderStatus, String userName) {

        return ygOrderMapper.selectOrderListByHeXiao(queryInfo, orderStatus, userName);
    }

    @Override
    public Boolean hasHeXiaoOrder(Long userId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andUserIdEqualTo(userId).andOrderStatusNotEqualTo(OrderStatus.TradeClosed.name()).andOrderTypeEqualTo(OrderType.HeXiao.name());
        return ygOrderMapper.countByExample(example) > 0 ? true : false;
    }

    @Override
    public YgOrder findLastOrder(OrderType orderType, Boolean paid) {
        return ygOrderMapper.selectLastOrder(orderType, paid);
    }

    @Override
    public int closeOrderBySystem(Long orderId, String reason) {
        YgOrder ygOrder = new YgOrder(orderId, reason);
        return this.updateByOrderId(ygOrder);
    }

    @Override
    public YgOrder getOrderByOrderId(Long orderId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdEqualTo(orderId).andStatusEqualTo(DataStatus.Valid.name());
        List<YgOrder> list = ygOrderMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public Message saveImportThirdOrder(List<YgOrder4ImportModel> agentOrderList, Long userId) {
        if (agentOrderList != null && agentOrderList.size() > 0) {
            List<YgStock> stocks = new ArrayList<YgStock>();
            Map<String, List<YgOrder4ImportModel>> subDetailMap = new LinkedHashMap<String, List<YgOrder4ImportModel>>();
            List<Long> keys = new ArrayList<Long>();

            Map<String, Long> skuCountMap = new HashMap<String, Long>();
            List<String> skuCodes = new ArrayList<String>();
            // 按照订单编号 分组

            for (YgOrder4ImportModel model : agentOrderList) {
                Long count = skuCountMap.get(model.getSkuCode());
                if (count == null) {
                    count = model.getQuantity();
                    skuCountMap.put(model.getSkuCode(), count);
                    skuCodes.add(model.getSkuCode());
                } else {
                    count = count + model.getQuantity();
                    skuCountMap.put(model.getSkuCode(), count);
                }

                List<YgOrder4ImportModel> subDetails = subDetailMap.get(model.getOrderId() + "");
                if (subDetails == null) {
                    subDetails = new ArrayList<YgOrder4ImportModel>();
                    subDetailMap.put(model.getOrderId() + "", subDetails);
                    if (!keys.contains(model.getOrderId()))
                        keys.add(model.getOrderId());
                }
                subDetails.add(model);
            }
            // 校验库存
            /*
             * Message msg = checkImportOrderStock(skuCodes, skuCountMap); if
             * (msg.getType().equals(Message.Type.error)) { return msg; }
             */
            List<YgOrder> orderList = new ArrayList<YgOrder>();
            if (keys.size() > 0) {
                for (Long key : keys) {
                    List<YgOrder4ImportModel> list = agentOrderList.stream().filter(m -> m.getOrderId().equals(key)).collect(Collectors.toList());
                    // 获取用户Id
                    Boolean isNew = false;
                    YgOrder order = new YgOrder();
                    YgUser user = userService.findByUserName(list.get(0).getUserName());
                    if (user != null) {
                        order.setUserId(user.getId());
                    } else {
                        user = userService.register(list.get(0).getUserName(), "123456a", null, "http://img.yiigoo.com/default/head-women.jpg", "壹果");
                        order.setUserId(user.getId());
                        isNew = true;
                    }
                    Long orderCode = key;
                    Long orderId = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());
                    order.setOrderId(orderId);
                    order.setParentId(orderId);
                    order.setSupplierId(32L);
                    order.setReceiver(list.get(0).getReceiver());
                    order.setProvinceName(list.get(0).getProvinceName());
                    order.setCityName(list.get(0).getCityName());
                    order.setAreaName(list.get(0).getAreaName());
                    order.setAddress(list.get(0).getAddress());
                    order.setTelPhone(list.get(0).getTelPhone());
                    order.setSourceCode(list.get(0).getSourceCode());
                    order.setUserRemark(orderCode.toString());
                    BigDecimal productPrice = new BigDecimal(0);

                    List<YgOrderDetail> detailList = new ArrayList<YgOrderDetail>();
                    for (YgOrder4ImportModel model : list) {
                        YgOrderDetail detail = new YgOrderDetail();
                        YgSku sku = skuService.findBySkuCode(model.getSkuCode(), PromotionType.Ordinary);
                        YgProduct product = productService.findById(sku.getProductId());
                        YgProductImages image = ygProductImagesService.findMainImgByProductId(sku.getProductId());

                        detail.setOrderId(order.getOrderId());
                        detail.setSkuId(sku.getId());
                        detail.setSkuCode(sku.getSkuCode());
                        detail.setSupplierId(32L);
                        detail.setProductName(product.getProductName());
                        detail.setShortName(product.getShortName());
                        detail.setSize(sku.getSizeName());
                        detail.setImageUrl(image.getImagePath());
                        detail.setQuantity(model.getQuantity());
                        detail.setUnitName(product.getUnitName());
                        detail.setPromotionType(PromotionType.Ordinary);
                        detail.setSalePrice(model.getSalesPrice());

                        productPrice = productPrice.add(detail.getSalePrice().multiply(new BigDecimal(detail.getQuantity())));
                        detailList.add(detail);

                        YgStock stock = new YgStock();
                        stock.setSkuCode(detail.getSkuCode());
                        stock.setAmount(detail.getQuantity());

                        stocks.add(stock);
                    }

                    order.setManjianPrice(new BigDecimal(0));
                    if (isNew) {
                        order.setYouhuijuanPrice(new BigDecimal(20));
                        order.setCouponDetailId(26L);

                    } else {
                        order.setYouhuijuanPrice(new BigDecimal(50));
                        order.setCouponDetailId(26L);
                    }

                    order.setExpressPrice(new BigDecimal(0));
                    order.setProductPrice(productPrice);
                    if (productPrice.subtract(order.getYouhuijuanPrice()).compareTo(new BigDecimal(199)) >= 0) {
                        order.setExpressPrice(new BigDecimal(0));
                    } else
                        order.setExpressPrice(new BigDecimal(10L));

                    order.setTotalPrice(productPrice.subtract(order.getYouhuijuanPrice()).add(order.getExpressPrice()));

                    order.setOrderStatus(OrderStatus.WaitingPay);

                    order.setPaidPrice(new BigDecimal(0));
                    order.setPayType(PayType.WeChat);
                    order.setNewCustomDisPrice(new BigDecimal(0));
                    order.setPackDisPrice(new BigDecimal(0));
                    order.setCreateTime(new Date());
                    order.setStatus(DataStatus.Valid);
                    order.setCommentStatus(CommentStatus.UnComplete);

                    order.setOrderDetail(detailList);
                    orderList.add(order);
                }
            }
            this.saveOrderBatch(orderList);

            // stockService.reduceStock(stocks, "saveImportThirdOrder");

        }
        return Message.success("没有订单数据");
    }

    @Override
    public List<Map<String, Object>> selectOrderByProductName(String productName) {

        return ygOrderMapper.selectOrderByProductName(productName);
    }

    @Override
    public List<String> getNoSendOrderListBySupplier(Long supplierId) {
        return ygOrderMapper.selectNoSendOrderBySupplier(supplierId);
    }

    @Override
    public Message updateLogistics(List<YgLogistics> ygLogistics) {
        try {

            List<YgOrder> orderlist = new ArrayList<YgOrder>();
            List<YgOrderDetail> sendDetailList = new ArrayList<YgOrderDetail>();
            List<String> orderIds = new ArrayList<String>();

            List<String> detailMarkList = new ArrayList<>();
            List<String> logisticsMarkList = new ArrayList<>();

            List<YgLogistics> newLogisticsList = new ArrayList<>();
            Date now = new Date();
            for (YgLogistics log : ygLogistics) {
                // 过滤重复明细发货数据
                String detailMark = log.getOrderId() + "_" + log.getAddress() + "_" + log.getExpressCode();
                if (detailMarkList.contains(detailMark)) {
                    continue;
                }
                detailMarkList.add(detailMark);

                // 过滤已存在发货物流信息
                String logisticsMark = log.getOrderId() + "_" + log.getExpressCode();
                if (!logisticsMarkList.contains(logisticsMark)) {
                    logisticsMarkList.add(logisticsMark);
                    if (!ygLogisticsService.isExist(log.getOrderId(), log.getExpressCode())) {
                        log.setSendTime(now);
                        log.setCreateTime(now);
                        log.setLogisticsCode(getLogicCode(log.getExpressCompany()));
                        newLogisticsList.add(log);
                    }
                }

                if (!orderIds.contains(log.getOrderId())) {
                    orderIds.add(log.getOrderId());
                    YgOrder o = new YgOrder();
                    o.setOrderId(Long.valueOf(log.getOrderId()));
                    o.setOrderStatus(OrderStatus.WaitingSign);
                    o.setSendTime(now);
                    orderlist.add(o);
                }
                YgOrderDetail orderDetail = new YgOrderDetail();
                orderDetail.setDetailStatus(OrderDetailStatus.WaitingSign);
                orderDetail.setOrderId(Long.valueOf(log.getOrderId()));
                orderDetail.setSkuCode(log.getAddress());
                orderDetail.setSendMark(log.getExpressCode());
                sendDetailList.add(orderDetail);
            }
            ygLogisticsService.addLogisticsBatch(newLogisticsList);
            ygOrderMapper.updateStatus4SendByTask(orderlist);
            orderDetailMapper.updateDetailSendBatchBySkuCde(sendDetailList);
            kidsOrderLogisticsService.addBatchByYgLogistics(ygLogistics);
            this.addQuartzJob(orderlist);

        } catch (Exception ex) {

            return Message.error("更新失败!");
        }

        return Message.success("更新成功");
    }

    private void addQuartzJob(List<YgOrder> orderList) {
        for (YgOrder ygOrder : orderList) {
            executorService.execute(new Runnable() {
                public void run() {
                    scheduleJobService.addBalanceJob(ygOrder.getOrderId(), ygOrder.getSendTime(), "task");
                }
            });

        }
    }

    private String getLogicCode(String expressCompany) {
        String code = "";

        if (expressCompany.startsWith("申通"))
            return "STO";
        if (expressCompany.startsWith("中通"))
            return "ZTO";
        if (expressCompany.startsWith("顺丰"))
            return "SF";
        if (expressCompany.startsWith("圆通"))
            return "YTO";
        if (expressCompany.startsWith("韵达"))
            return "YD";
        if (expressCompany.startsWith("百世"))
            return "HTKY";
        if (expressCompany.startsWith("天天快递"))
            return "HHTT";
        if (expressCompany.startsWith("德邦"))
            return "DBL";
        if (expressCompany.startsWith("快捷快递"))
            return "FAST";

        return code;
    }

    @Override
    public List<Map<String, Object>> getOrderDetailBySupplier(Long q, Date startDate, Date endDate, OrderStatus orderStatus, String telPhone, Long supplierId) {
        return ygOrderMapper.selectOrderDetailBySupplier(q, startDate, endDate, orderStatus, telPhone, supplierId);

    }

    @Override
    public ResultSet<YgOrder> searchBySupplier(QueryInfo queryInfo, String q, OrderStatus orderStatus, Date startDate, Date endDate, Long supplierId,
                                               String telPhone) {
        List<YgOrder> list = ygOrderMapper.selectOrderBySupplier(queryInfo, q, orderStatus, startDate, endDate, supplierId, telPhone);
        int count = ygOrderMapper.countBySupplier(q, orderStatus, startDate, endDate, supplierId, telPhone);

        ResultSet<YgOrder> resultSet = new ResultSet<YgOrder>(count, list);
        return resultSet;
    }

    @Override
    public List<YgOrder> searchOrderBySupplier(QueryInfo queryInfo, String q, OrderStatus orderStatus, Date startDate, Date endDate, Long supplierId,
                                               String telPhone) {
        List<YgOrder> list = ygOrderMapper.selectOrderBySupplier(queryInfo, q, orderStatus, startDate, endDate, supplierId, telPhone);
        return list;
    }

    @Override
    public YgOrderInfoModel selectOrderDetailBySupplierOrderId(Long orderId, Long supplierId) {
        return ygOrderMapper.selectOrderDetailBySupplierOrderId(orderId, supplierId);
    }

    @Override
    public List<Map<String, Object>> selectOpenIdByOrder(List<YgLogistics> log) {
        return ygOrderMapper.selectOpenIdByOrder(log);
    }

    @Override
    public int selectReturnByOrder(Long supplierId, Long orderId, String skuCode) {
        return ygOrderMapper.selectReturnByOrder(supplierId, orderId, skuCode);
    }

    @Override
    public List<Long> findExitOrderIds(List<Long> orderIds) {
        return ygOrderMapper.findExitOrderIds(orderIds);
    }

    @Override
    public List<YgOrder> findByPaidTimeHasDetail(Date startDate, Date endDate, String sourceCode, OrderStatus... orderStatus) {
        return this.findByPaidTimeHasDetail(startDate, endDate, sourceCode, null, orderStatus);
    }

    @Override
    public List<YgOrder> findByPaidTimeHasDetail(Date startDate, Date endDate, String sourceCode, Long supplierId, OrderStatus... orderStatus) {
        return ygOrderMapper.findByPaidTimeHasDetail(startDate, endDate, sourceCode, supplierId,
                orderStatus == null || orderStatus.length == 0 ? null : orderStatus);
    }

    @Override
    public List<YgOrder> findOrderDetailByOrderNoList(List<Long> orderNos) {
        if (!CollectionUtils.isEmpty(orderNos)) {
            return ygOrderMapper.selectOrderDetailByOrderIdList(orderNos);
        }
        return new ArrayList<>();
    }

    @Override
    public List<Map<String, Object>> getTotalPriceWithMonth(Long userId, Date startDate, Date endDate) {
        return ygOrderMapper.getTotalPriceWithMonth(userId, startDate, endDate);
    }

    @Override
    public List<YgOrder> findOrderDetailByReturn(Date startDate, Date endDate, String returnCode, ReturnType returnType, ReturnStatus... returnStatus) {
        return ygOrderMapper.findOrderDetailByReturn(startDate, endDate, returnCode, returnType, returnStatus);
    }

    @Override
    public List<YgOrder> findAgentOrderByPaidTimeHasDetail(Date startDate, Date endDate, Long userId, OrderStatus... orderStatus) {
        return ygOrderMapper.findAgentOrderByPaidTimeHasDetail(startDate, endDate, userId, orderStatus);
    }

    @Override
    public List<YgOrder> findGroupMemberOrderByPaidTimeHasDetail(Date startDate, Date endDate, String groupTag, OrderStatus... orderStatus) {

        return ygOrderMapper.findGroupMemberOrderByPaidTimeHasDetail(startDate, endDate, groupTag, orderStatus);
    }

    @Override
    public List<YgOrder> findRODByOrderId(List<Long> orderIds, ReturnType returnType, ReturnStatus... returnStatus) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return null;
        }
        return ygOrderMapper.findRODByOrderId(orderIds, returnType, returnStatus);
    }

    @Override
    public List<YgOrder> findOrderBySendTime(Date startDate, Date endDate) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andSendTimeBetween(startDate, endDate).andStatusEqualTo(DataStatus.Valid.name())
                .andOrderStatusNotEqualTo(OrderStatus.TradeClosed.name());
        return ygOrderMapper.selectByExample(example);
    }

    @Override
    public List<YgOrder> findByParentId(Long parentId) {
        if (parentId == null) {
            return new ArrayList<>();
        }
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andParentIdEqualTo(parentId).andOrderIdNotEqualTo(parentId);
        return ygOrderMapper.selectByExample(example);
    }

    @Override
    public int transferOrder(Long sourceUserId, Long targetUserId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andUserIdEqualTo(sourceUserId);
        YgOrder record = new YgOrder();
        record.setUserId(targetUserId);
        return ygOrderMapper.updateByExampleSelective(record, example);
    }

    @Override
    public List<YgOrder> findByCreateTimeHasDetail(Date startDate, Date endDate, List<String> filterSourceList) {
        return ygOrderMapper.selectByCreateTimeHasDetail(startDate, endDate, CollectionUtils.isEmpty(filterSourceList) ? null : filterSourceList);
    }

    @Override
    public Boolean isExist(Long orderId) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdEqualTo(orderId).andStatusEqualTo(DataStatus.Valid.name());
        int count = ygOrderMapper.countByExample(example);
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public int countDetailBySupplierId(Long orderId, Long supplierId) {
        YgOrderDetailExample example = new YgOrderDetailExample();
        example.createCriteria().andOrderIdEqualTo(orderId).andSupplierIdEqualTo(supplierId);
        return orderDetailMapper.countByExample(example);
    }

    @Override
    public List<YgOrder> findOrderBySendTimeHasDetail(Date startDate, Date endDate, Long supplierId, String... orderType) {
        return ygOrderMapper.selectBySendTimeHasDetail(startDate, endDate, supplierId, orderType == null || orderType.length == 0 ? null : orderType);
    }

    @Override
    public List<YgOrder> findOrderBySendTimeHasDetail(Date startDate, Date endDate, Long supplierId) {
        return findOrderBySendTimeHasDetail(startDate, endDate, supplierId, OrderType.Ordinary.name(), OrderType.GroupBuying.name(), OrderType.KanJia.name(),
                OrderType.HeXiao.name());
    }

    @Override
    public int updateOrderSendStatus(Long orderId, Date sendTime) {
        YgOrder o = new YgOrder();
        o.setOrderId(orderId);
        o.setSendTime(sendTime);
        return this.updateByOrderId(o);
    }

    @Override
    public YgOrder findFirstSendOrder(Long userId, Date limitDate, Long limitOrderId) {
        return ygOrderMapper.selectFirstSendOrder(userId, limitDate, limitOrderId);
    }

    @Override
    public Message validateAccountPrice(Long userId, BigDecimal accountPrice, BigDecimal totalPrice) {
        if (accountPrice != null && accountPrice.compareTo(BigDecimal.ZERO) > 0) {
            YgUserBalance balance = ygUserBalanceService.findByUserId(userId);
            if (balance.getBalancePrice().compareTo(accountPrice) < 0) { // 账户余额小于当前是使用金额
                return Message.error("账户余额有误，请重试。", null);
            }
            if (accountPrice.compareTo(totalPrice) > 0) {// 使用的虚拟金额大于订单的实际金额
                return Message.error("账户余额有误，请重试。", null);
            }
        }
        return Message.success(null);
    }

    @Override
    public int updateOrderStatusByOrderId(OrderStatus orderStatus, Long orderId) {
        try {
            ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "拼团完成", "订单拼团成功");
            return ygOrderMapper.updateOrderStatusByOrderId(orderStatus, orderId);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0;
    }

    @Override
    public List<YgOrder> findByGroupBuyId(OrderStatus orderStatus, List<Long> groupBuyIdList) {
        if (CollectionUtils.isEmpty(groupBuyIdList)) {
            return new ArrayList<>();
        }
        return ygOrderMapper.selectByGroupBuyId(orderStatus, groupBuyIdList);
    }

    @Override
    public ResultSet<Map<String, Object>> selectNoSendOrderList(QueryInfo queryInfo, Date startDate,
                                                                Date endDate) {
        List<Map<String, Object>> list = ygOrderMapper.selectNoSendOrderList(queryInfo, startDate, endDate);

        int count = ygOrderMapper.countNoSendOrderList(startDate, endDate);
        ResultSet<Map<String, Object>> resultSet = new ResultSet<Map<String, Object>>(count, list);
        return resultSet;
    }

    @Override
    public ResultSet<Map<String, Object>> selectNoSendOrderDetail(
            QueryInfo queryInfo, Long supplierId, Date startDate, Date endDate) {
        List<Map<String, Object>> list = ygOrderMapper.selectNoSendOrderDetail(queryInfo, supplierId, startDate, endDate);

        int count = ygOrderMapper.countNoSendOrderDetail(supplierId, startDate, endDate);
        ResultSet<Map<String, Object>> resultSet = new ResultSet<Map<String, Object>>(count, list);
        return resultSet;
    }

    @Override
    public int updateWdtCode(Long... orderIds) {
        if (orderIds == null || orderIds.length == 0) {
            return 0;
        }
        return ygOrderMapper.updateWdtCode(orderIds);
    }

    @Override
    public boolean existedByOutCode(String outCode) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andSourceCodeEqualTo(outCode).andStatusEqualTo(DataStatus.Valid.name());
        int count = ygOrderMapper.countByExample(example);
        return count > 0;
    }

    @Override
    public BigDecimal getTotalSharePrice(Long orderId) {
        if (orderId == null) {
            return BigDecimal.ZERO;
        }
        List<YgOrderDetail> orderDetailList = orderDetailMapper.selectByOrderId(orderId);
        return orderDetailList.parallelStream().filter(od -> od.getShareRate() != null)
                .map(od -> {
                    BigDecimal orderSharePrice = od.getRealPrice().add(od.getAccountPrice());
                    return orderSharePrice.multiply(od.getShareRate()).setScale(1, BigDecimal.ROUND_HALF_UP);
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    public List<YgOrderInfoModel> findOrderInfoByPayTime(Date startTime, Date endTime, String platformNo) {
        return ygOrderMapper.selectOrderInfoByPayTime(startTime, endTime, platformNo);
    }

    @Override
    public YgOrder findOrderDetailByOrderIdForThird(Long orderId) {
        return ygOrderMapper.selectOrderDetailByOrderIdForThird(orderId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateWdtCodeBatch(List<PushOrderToWdtResult> resultList) {
        if (CollectionUtils.isEmpty(resultList)) {
            return 0;
        }
        new AbstractSplitListTemplate<PushOrderToWdtResult>(resultList) {
            @Override
            public int execute(List<PushOrderToWdtResult> recordList) {
                ygOrderMapper.updateWdtCodeBatch(resultList);
                orderDetailMapper.updateWdtCodeBatch(resultList);
                return 1;
            }
        }.split();
        return 1;
    }

    @Override
    public int updateWdtCode(PushOrderToWdtResult pushOrderToWdtResult) {
        return updateWdtCodeBatch(Collections.singletonList(pushOrderToWdtResult));
    }

    @Override
    public List<YgOrder> findOrderListByOrderIds(List<Long> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return Collections.emptyList();
        }
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andOrderIdIn(orderIds);
        return ygOrderMapper.selectByExample(example);
    }

    @Override
    public List<YgOrder> findOrderDetailBySupplier(Long supplierId, OrderDetailStatus orderStatus) {
        return ygOrderMapper.selectOrderDetailListBySupplier(supplierId, orderStatus);
    }

    @Override
    public YgOrder findByReleateId(Long releateId, OrderType orderType) {
        YgOrderExample example = new YgOrderExample();
        example.createCriteria().andReleationIdEqualTo(releateId).andOrderTypeEqualTo(orderType.name()).andStatusEqualTo(DataStatus.Valid.name());
        List<YgOrder> orderList = ygOrderMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(orderList)) {
            return orderList.get(0);
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
    @Override
    public Message saveZeroOrder(YgSkuInfo skuInfo, YgUserAddress address, String platformNo, AppType appType) {
        YgOrder order = new YgOrder();
        // 设置收货信息
        order.setReceiver(address.getReceiver());
        order.setProvinceName(address.getProvinceName());
        order.setCityName(address.getCityName());
        order.setAreaName(address.getAreaName());
        order.setAddress(address.getAddress());
        order.setTelPhone(address.getTelPhone());
        // 保存主单
        Long orderId = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());
        order.setOrderId(orderId);
        order.setParentId(orderId);
        order.setUserId(address.getUserId());
        order.setTotalPrice(BigDecimal.ZERO);
        order.setProductPrice(BigDecimal.ZERO);
        order.setExpressPrice(BigDecimal.ZERO);
        order.setManjianPrice(BigDecimal.ZERO);
        order.setYouhuijuanPrice(BigDecimal.ZERO);
        order.setGroupDisPrice(BigDecimal.ZERO);
        order.setNewCustomDisPrice(BigDecimal.ZERO);
        order.setPackDisPrice(BigDecimal.ZERO);
        order.setBmdisPrice(BigDecimal.ZERO);
        order.setAccountPrice(BigDecimal.ZERO);
        order.setPayType(PayType.Account);
        order.setPaidTime(new Date());
        order.setSupplierId(skuInfo.getSupplierId());
        order.setOrderStatus(OrderStatus.WaitingSend);
        order.setCreateTime(new Date());
        order.setOrderType(OrderType.Ordinary);
        order.setAppType(appType);
        if (StringUtils.isBlank(platformNo) || Constant.YIIGOO_PLATFORM_NO.equals(platformNo)) {
            order.setPlatformNo(Constant.YIIGOO_PLATFORM_NO);
            order.setPlatformName("yiigoo");
        } else {
            YgPlatform platform = ygPlatformService.findByPlatformNo(platformNo, appType);
            order.setPlatformNo(platform.getPlatformNo());
            order.setPlatformName(platform.getName());
        }

        YgOrderDetail detail = new YgOrderDetail();
        detail.setOrderId(orderId);
        detail.setProductId(skuInfo.getProductId());
        detail.setProductName(skuInfo.getProductName());
        detail.setPromotionType(PromotionType.ManZeng);
        detail.setQuantity(skuInfo.getQuantity());
        detail.setSize(skuInfo.getSizeName());
        detail.setSupplierId(skuInfo.getSupplierId());
        detail.setSkuCode(skuInfo.getSkuCode());
        detail.setSkuId(skuInfo.getSkuId());
        detail.setUnitName(skuInfo.getUnitName());
        detail.setImageUrl(skuInfo.getImgPath());
        detail.setShortName(skuInfo.getShortName());
        detail.setSalePrice(BigDecimal.ZERO);
        detail.setForeverRate(BigDecimal.ZERO);
        detail.setShareRate(BigDecimal.ZERO);
        detail.setYhqDisPrice(BigDecimal.ZERO);
        detail.setMjDisPrice(BigDecimal.ZERO);
        detail.setBmDisPrice(BigDecimal.ZERO);
        detail.setAccountPrice(BigDecimal.ZERO);
        detail.setExpressPrice(BigDecimal.ZERO);
        detail.setPackDisPrice(BigDecimal.ZERO);
        detail.setVipDisPrice(BigDecimal.ZERO);
        detail.setNewCustomDisPrice(BigDecimal.ZERO);
        detail.setRealPrice(BigDecimal.ZERO);
        detail.setCostPrice(skuInfo.getCostPrice());

        YgStock stock = new YgStock();
        stock.setSkuCode(skuInfo.getSkuCode());
        stock.setAmount(skuInfo.getQuantity());
        try {
            this.save(order);
            ygOrderLogService.addOrderLog(order.getOrderId(), order.getOrderStatus(), address.getUserId().toString(),
                    "主订单保存成功 ;order=" + order.toString());
        } catch (Exception e) {
            ygOrderLogService.addOrderLog(order.getOrderId(), order.getOrderStatus(), address.getUserId().toString(),
                    "主订单保存失败;order=" + order.toString());
            logger.error("主单保存失败。orderInfo:" + order.toString());
            e.printStackTrace();
            return Message.error("提交订单失败！", orderId);
        }

        orderDetailMapper.insertBatch(Collections.singletonList(detail));
        // 扣减库存
        stockService.reduceStock(Collections.singletonList(stock), "saveActionOrder");
        // 异步推送到旺店通
        wdtSyncOrderClient.syncQybOrder(Collections.singletonList(order.getOrderId()));
        return Message.success(order.getOrderId());
    }

    @Override
    public List<YgOrder> findByPaidTime(Date startTime, Date endTime, String platformNo) {
        return ygOrderMapper.selectByPaidTime(startTime, endTime, platformNo);
    }
}
